diff --git a/frontend/src/hooks/useSliceUpload.tsx b/frontend/src/hooks/useSliceUpload.tsx index 14c8d4c..1fcc62e 100644 --- a/frontend/src/hooks/useSliceUpload.tsx +++ b/frontend/src/hooks/useSliceUpload.tsx @@ -99,8 +99,14 @@ export function useFileSliceUpload( if (!task) { return; } - const { reqId, key } = task; + const { reqId, key, controller } = task; const { loaded, i, j, files, totalSize } = fileInfo; + + // 检查是否已取消 + if (controller.signal.aborted) { + throw new Error("Upload cancelled"); + } + const formData = await buildFormData({ file: files[i], i, @@ -110,6 +116,7 @@ export function useFileSliceUpload( let newTask = { ...task }; await uploadChunk(key, formData, { + signal: controller.signal, onUploadProgress: (e) => { const loadedSize = loaded + e.loaded; const curPercent = Number((loadedSize / totalSize) * 100).toFixed(2); @@ -141,9 +148,10 @@ export function useFileSliceUpload( reqId, isCancel: false, cancelFn: () => { - task.controller.abort(); + // 使用 newTask 的 controller 确保一致性 + newTask.controller.abort(); cancelUpload?.(reqId); - if (task.updateEvent) window.dispatchEvent(new Event(task.updateEvent)); + if (newTask.updateEvent) window.dispatchEvent(new Event(newTask.updateEvent)); }, }; updateTaskList(newTask); @@ -153,8 +161,16 @@ export function useFileSliceUpload( let loaded = 0; for (let i = 0; i < files.length; i++) { + // 检查是否已取消 + if (newTask.controller.signal.aborted) { + throw new Error("Upload cancelled"); + } const { slices } = files[i]; for (let j = 0; j < slices.length; j++) { + // 检查是否已取消 + if (newTask.controller.signal.aborted) { + throw new Error("Upload cancelled"); + } await uploadSlice(newTask, { loaded, i, @@ -219,9 +235,10 @@ export function useFileSliceUpload( reqId, isCancel: false, cancelFn: () => { - task.controller.abort(); + // 使用 newTask 的 controller 确保一致性 + newTask.controller.abort(); cancelUpload?.(reqId); - if (task.updateEvent) window.dispatchEvent(new Event(task.updateEvent)); + if (newTask.updateEvent) window.dispatchEvent(new Event(newTask.updateEvent)); }, }; updateTaskList(newTask); @@ -232,13 +249,26 @@ export function useFileSliceUpload( // 逐个处理文件 for (let i = 0; i < files.length; i++) { + // 检查是否已取消 + if (newTask.controller.signal.aborted) { + throw new Error("Upload cancelled"); + } + const file = files[i]; console.log(`[useSliceUpload] Processing file ${i + 1}/${files.length}: ${file.name}`); const result = await streamSplitAndUpload( file, - (formData, config) => uploadChunk(task.key, formData, config), + (formData, config) => uploadChunk(task.key, formData, { + ...config, + signal: newTask.controller.signal, + }), (currentBytes, totalBytes, uploadedLines) => { + // 检查是否已取消 + if (newTask.controller.signal.aborted) { + return; + } + // 更新进度 const overallBytes = totalProcessedBytes + currentBytes; const curPercent = Number((overallBytes / totalSize) * 100).toFixed(2); @@ -260,9 +290,9 @@ export function useFileSliceUpload( 1024 * 1024, // 1MB chunk size { reqId, - hasArchive: task.hasArchive, - prefix: task.prefix, - signal: task.controller.signal, + hasArchive: newTask.hasArchive, + prefix: newTask.prefix, + signal: newTask.controller.signal, maxConcurrency: 3, } ); diff --git a/frontend/src/utils/file.util.ts b/frontend/src/utils/file.util.ts index dc14d6c..096f15b 100644 --- a/frontend/src/utils/file.util.ts +++ b/frontend/src/utils/file.util.ts @@ -442,6 +442,11 @@ export async function streamSplitAndUpload( * 上传单行内容 */ async function uploadLine(line: string, index: number): Promise { + // 检查是否已取消 + if (signal?.aborted) { + throw new Error("Upload cancelled"); + } + if (!line.trim()) { skippedEmptyCount++; return; @@ -455,6 +460,11 @@ export async function streamSplitAndUpload( const slices = sliceFile(lineFile, DEFAULT_CHUNK_SIZE); const checkSum = await calculateSHA256(slices[0]); + // 检查是否已取消(计算哈希后) + if (signal?.aborted) { + throw new Error("Upload cancelled"); + } + const formData = new FormData(); formData.append("file", slices[0]); formData.append("reqId", reqId.toString()); diff --git a/frontend/src/utils/request.ts b/frontend/src/utils/request.ts index aed6743..23b7c2b 100644 --- a/frontend/src/utils/request.ts +++ b/frontend/src/utils/request.ts @@ -92,6 +92,14 @@ class Request { }); } + // 监听 AbortSignal 来中止请求 + if (config.signal) { + config.signal.addEventListener("abort", () => { + xhr.abort(); + reject(new Error("上传已取消")); + }); + } + // 监听上传进度 xhr.upload.addEventListener("progress", function (event) { if (event.lengthComputable) {