import NProgress from 'nprogress'; import 'nprogress/nprogress.css'; import { toast } from 'react-toastify'; import { nanoid } from 'nanoid'; import { toastLogin } from '@kevisual/resources/pages/message/ToastLogin'; type ConvertOpts = { appKey?: string; version?: string; username?: string; directory?: string; }; export const uploadFileChunked = async (file: File, opts: ConvertOpts) => { const { directory } = opts; return new Promise(async (resolve, reject) => { const token = localStorage.getItem('token'); if (!token) { toastLogin(); return; } const taskId = nanoid(); const filename = file.name; const load = toast.loading(`${filename} 上传中...`); NProgress.start(); // const eventSource = new EventSource('http://49.232.155.236:11015/api/s1/events?taskId=' + taskId); const eventSource = new EventSource('/api/s1/events?taskId=' + taskId); // 监听服务器推送的进度更新 eventSource.onmessage = function (event) { console.log('Progress update:', event.data); const parseIfJson = (data: string) => { try { return JSON.parse(data); } catch (e) { return data; } }; const receivedData = parseIfJson(event.data); if (typeof receivedData === 'string') return; const progress = receivedData.progress; const progressFixed = progress.toFixed(2); console.log('progress', progress, progressFixed); toast.update(load, { render: `${filename} \n上传中...${progressFixed}%`, isLoading: true, autoClose: false }); if (progress) { NProgress.set(progress); } }; eventSource.onerror = function (event) { console.log('eventSource.onerror', event); reject(event); }; const chunkSize = 1 * 1024 * 1024; // 1MB const totalChunks = Math.ceil(file.size / chunkSize); for (let currentChunk = 0; currentChunk < totalChunks; currentChunk++) { const start = currentChunk * chunkSize; const end = Math.min(start + chunkSize, file.size); const chunk = file.slice(start, end); const formData = new FormData(); formData.append('file', chunk, file.name); formData.append('chunkIndex', currentChunk.toString()); formData.append('totalChunks', totalChunks.toString()); if (directory) { formData.append('directory', directory); } try { const res = await fetch('/api/s1/resources/upload/chunk?taskId=' + taskId, { method: 'POST', body: formData, headers: { 'task-id': taskId, Authorization: `Bearer ${token}`, }, }).then((response) => response.json()); fetch('/api/s1/events/close?taskId=' + taskId); eventSource.close(); NProgress.done(); toast.dismiss(load); resolve(res); // console.log(`Chunk ${currentChunk + 1}/${totalChunks} uploaded`, res); } catch (error) { console.log('Error uploading chunk', error); reject(error); return; } } }); };