diff --git a/global.d.ts b/global.d.ts index daa33b4..e672a7b 100644 --- a/global.d.ts +++ b/global.d.ts @@ -1,5 +1,5 @@ interface IBaseAPI { - uploadFile: (path: string) => void + uploadFile: (path: File[]) => void setTitle: (value: string) => void onUploadProgress: (progress: unknown) => void } diff --git a/src/index.ts b/src/index.ts index a50fb39..22abd62 100644 --- a/src/index.ts +++ b/src/index.ts @@ -25,9 +25,9 @@ const createWindow = (): void => { win.setTitle(title) }) - ipcMain.on('upload', (event, filePath) => { + ipcMain.on('upload', (event, filePaths: string[]) => { // 在后台线程中处理文件上传 - uploadFile(filePath, event.sender); + uploadFile(filePaths, event.sender); }); // and load the index.html of the app. diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx index 41936aa..8b415b8 100644 --- a/src/pages/home/index.tsx +++ b/src/pages/home/index.tsx @@ -1,51 +1,65 @@ -import { message, Upload, UploadProps } from 'antd' +import { Button, message, Upload } from 'antd' import { useEffect, useState } from 'react'; +import type { GetProp, UploadFile, UploadProps } from 'antd'; + +type FileType = Parameters>[0]; const { Dragger } = Upload; -const props: UploadProps = { - name: 'file', - multiple: true, - capture: 'user', - hasControlInside: false, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - action: false, - onChange(info) { - console.log('info', info) - const { status } = info.file; - if (status !== 'uploading') { - console.log(info.file, info.fileList); - } - if (status === 'done') { - message.success(`${info.file.name} file uploaded successfully.`); - } else if (status === 'error') { - message.error(`${info.file.name} file upload failed.`); - } - }, - onDrop(e) { - console.log('Dropped files', e.dataTransfer.files); - }, -}; - export default () => { const [progress, setProgress] = useState(0) - - useEffect(() => { - window.baseAPI.onUploadProgress((_progress: unknown) => { - console.log('_progress', _progress) - setProgress(_progress) - }) - }, []) + const [fileList, setFileList] = useState([]); + const [uploading, setUploading] = useState(false); + + const handleUpload = () => { + const formData = new FormData(); + fileList.forEach((file) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + formData.append('files[]', file as FileType); + }); + setUploading(true); + const filePaths = fileList.map((_file: any) => _file.path) + console.log('filePaths', filePaths) + window.baseAPI.uploadFile(filePaths) + setUploading(false) + }; + + + const uploadProps: UploadProps = { + name: 'file', + multiple: true, + capture: 'user', + hasControlInside: false, + onRemove: (file) => { + const index = fileList.indexOf(file); + const newFileList = fileList.slice(); + newFileList.splice(index, 1); + setFileList(newFileList); + }, + beforeUpload: (file) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + setFileList([...fileList, file]); + + return false; + }, + onDrop(e) { + console.log('Dropped files', e.dataTransfer.files); + }, + fileList, + }; + return (
- +

✋{progress}

文件拖拽到这上传

+
) } \ No newline at end of file diff --git a/src/preload.ts b/src/preload.ts index 7c56129..f0fd8a9 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -10,7 +10,7 @@ contextBridge.exposeInMainWorld('versions', { contextBridge.exposeInMainWorld('baseAPI', { setTitle: (title: string) => ipcRenderer.send('set-title', title), - uploadFile: (filePath: string) => ipcRenderer.send('upload', filePath), + uploadFile: (filePaths: string[]) => ipcRenderer.send('upload', filePaths), onUploadProgress: (cb: (progress: string) => void) => ipcRenderer.on('upload-progress', (_event, progress) => { cb?.(progress) diff --git a/src/utils/upload.ts b/src/utils/upload.ts index bfdbc3a..f80233e 100644 --- a/src/utils/upload.ts +++ b/src/utils/upload.ts @@ -1,22 +1,65 @@ +import { app } from 'electron'; import fs from 'fs'; +import path from 'node:path'; -export const uploadFile = (filePath: File['path'], sender) => { - const fileSize = fs.statSync(filePath).size; - let uploadedSize = 0; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export const uploadFile = (filePaths: string[], _sender: Electron.WebContents) => { + // 获取用户当前文件夹路径 + const saveDirectoryPath = app.getPath('userData'); + for (let i = 0; i < filePaths.length; i++) { + const fileName = path.basename(filePaths[i]); + const targetFilePath = path.join(saveDirectoryPath, fileName); + const fileStream = fs.createWriteStream(targetFilePath); + fileStream.write(fs.readFileSync(filePaths[i])); + fileStream.end(); + console.log('Uploaded file saved at:', targetFilePath); + } + // const fileSize = fs.statSync(filePath).size; + // let uploadedSize = 0; - const readStream = fs.createReadStream(filePath); + // const readStream = fs.createReadStream(filePath); - readStream.on('data', (chunk) => { - uploadedSize += chunk.length; - const progress = Math.round((uploadedSize / fileSize) * 100); - sender.send('upload-progress', progress); - }); + // readStream.on('data', (chunk) => { + // uploadedSize += chunk.length; + // const progress = Math.round((uploadedSize / fileSize) * 100); + // sender.send('upload-progress', progress); + // }); - readStream.on('end', () => { - sender.send('upload-success'); - }); + // readStream.on('end', () => { + // sender.send('upload-success'); + // }); - readStream.on('error', (err) => { - sender.send('upload-error', err.message); - }); + // readStream.on('error', (err) => { + // sender.send('upload-error', err.message); + // }); +} + +export const singleUpload = (file: File) => { + let path = file.path; //文件本地路径 + let stats = fs.statSync(path); //读取文件信息 + let chunkSize = 3 * 1024 * 1024; //每片分块的大小3M + let size = stats.size; //文件大小 + let pieces = Math.ceil(size / chunkSize); //总共的分片数 + function uploadPiece (i: number) { + //计算每块的结束位置 + let enddata = Math.min(size, (i + 1) * chunkSize); + let arr: any[] = []; + //创建一个readStream对象,根据文件起始位置和结束位置读取固定的分片 + let readStream = fs.createReadStream(path, { start: i * chunkSize, end: enddata - 1 }); + //on data读取数据 + readStream.on('data', (data)=>{ + arr.push(data) + }) + //on end在该分片读取完成时触发 + readStream.on('end', ()=>{ + //这里服务端只接受blob对象,需要把原始的数据流转成blob对象,这块为了配合后端才转 + let blob = new Blob(arr) + //新建formdata数据对象 + var formdata = new FormData(); + formdata.append("file", blob); + console.log('blob.size',blob.size) + formdata.append("size", size + ''); // 数字30被转换成字符串"30" + formdata.append("chunk", i + '');//第几个分片,从0开始 + formdata.append("chunks", pieces + '');//分片数 + } } \ No newline at end of file