2025-03-31 21:17:41 +08:00

114 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { randomId } from '../utils/random-id.ts';
import type { UploadOpts } from './upload-chunk.ts';
type ConvertOpts = {
appKey?: string;
version?: string;
username?: string;
directory?: string;
/**
* 文件大小限制
*/
maxSize?: number;
/**
* 文件数量限制
*/
maxCount?: number;
/**
* 是否不检查应用文件, 默认 true默认不检测
*/
noCheckAppFiles?: boolean;
};
export const uploadFiles = async (files: File[], opts: ConvertOpts, opts2: UploadOpts) => {
const { directory, appKey, version, username, noCheckAppFiles = true } = opts;
const { uploadProgress, createEventSource, baseUrl = '', token, FormDataFn } = opts2 || {};
const length = files.length;
const maxSize = opts.maxSize || 20 * 1024 * 1024; // 20MB
const totalSize = files.reduce((acc, file) => acc + file.size, 0);
if (totalSize > maxSize) {
const maxSizeMB = maxSize / 1024 / 1024;
uploadProgress?.error('有文件大小不能超过' + maxSizeMB + 'MB');
return;
}
const maxCount = opts.maxCount || 10;
if (length > maxCount) {
uploadProgress?.error(`最多只能上传${maxCount}个文件`);
return;
}
uploadProgress?.info(`上传中,共${length}个文件`);
return new Promise((resolve, reject) => {
const formData = new FormDataFn();
const webkitRelativePath = files[0]?.webkitRelativePath;
const keepDirectory = webkitRelativePath !== '';
const root = keepDirectory ? webkitRelativePath.split('/')[0] : '';
for (let i = 0; i < files.length; i++) {
const file = files[i];
if (keepDirectory) {
// relativePath 去除第一级
const webkitRelativePath = file.webkitRelativePath.replace(root + '/', '');
formData.append('file', file, webkitRelativePath); // 保留文件夹路径
} else {
formData.append('file', files[i], files[i].name);
}
}
if (directory) {
formData.append('directory', directory);
}
if (appKey && version) {
formData.append('appKey', appKey);
formData.append('version', version);
}
if (username) {
formData.append('username', username);
}
const searchParams = new URLSearchParams();
const taskId = randomId();
searchParams.set('taskId', taskId);
if (noCheckAppFiles) {
searchParams.set('noCheckAppFiles', '1');
}
const eventSource = new EventSource('/api/s1/events?taskId=' + taskId);
uploadProgress?.start('上传中...');
eventSource.onopen = async function (event) {
const res = await fetch('/api/s1/resources/upload?' + searchParams.toString(), {
method: 'POST',
body: formData,
headers: {
'task-id': taskId,
Authorization: `Bearer ${token}`,
},
}).then((response) => response.json());
console.log('upload success', res);
fetch('/api/s1/events/close?taskId=' + taskId);
eventSource.close();
uploadProgress?.done();
resolve(res);
};
// 监听服务器推送的进度更新
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 = Number(receivedData.progress);
const progressFixed = progress.toFixed(2);
console.log('progress', progress);
uploadProgress?.set(progress, { ...receivedData, taskId, progressFixed });
};
eventSource.onerror = function (event) {
console.log('eventSource.onerror', event);
reject(event);
};
});
};