92 lines
3.0 KiB
TypeScript
92 lines
3.0 KiB
TypeScript
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;
|
|
}
|
|
}
|
|
});
|
|
};
|