diff --git a/apps/web/src/api/assets/upload.ts b/apps/web/src/api/assets/upload.ts index 3a452945d..490b08df7 100644 --- a/apps/web/src/api/assets/upload.ts +++ b/apps/web/src/api/assets/upload.ts @@ -32,6 +32,8 @@ export const completeDirectUpload = async (data: { file_hash?: string /** 前端上传幂等 token(与 prepare 一致),同一次上传重发 complete 不重复建记录 */ client_upload_id?: string + /** 文件字节数;后端同名兜底去重需用它做大小校验,缺失(=0)时同名记录一律不判重 */ + file_size?: number }): Promise => { // complete 内含 OSS 存在性检查 + 建库 + 派单,放宽到 60s; // 超时不代表失败(记录可能已建成),调用方禁止超时后盲目重传整个文件 @@ -156,6 +158,8 @@ export const prepareDirectUploadHandle = async (data: { storage_key: prepared.storage_key, file_hash: data.fileHash, client_upload_id: data.clientUploadId, + // 透传文件字节数:后端同名兜底去重依赖大小校验,缺省会导致同名新视频被误判重复 + file_size: data.file.size, }), } } diff --git a/apps/web/src/test/api/assets.test.ts b/apps/web/src/test/api/assets.test.ts index 90967f1f5..cce914b2e 100644 --- a/apps/web/src/test/api/assets.test.ts +++ b/apps/web/src/test/api/assets.test.ts @@ -242,6 +242,20 @@ describe("assets API", () => { await expect(completeDirectUpload({ name: "test-item" })).resolves.not.toThrow() }) + it("请求体携带 file_size(后端同名兜底去重的大小校验依赖它)", async () => { + await completeDirectUpload({ + project_id: "p-1", + library_id: "l-1", + storage_key: "uploads/k.mp4", + file_size: 12345, + } as never) + const completeCalls = mockPost.mock.calls.filter( + ([u]: [string]) => u === "/upload/direct/complete", + ) + expect(completeCalls).toHaveLength(1) + expect(completeCalls[0][1]).toMatchObject({ file_size: 12345 }) + }) + it("should reject on API error", async () => { mockGet.mockRejectedValue(new Error("Network error")) mockPost.mockRejectedValue(new Error("Network error")) @@ -354,6 +368,8 @@ describe("assets API", () => { ([u]: [string]) => u === "/upload/direct/complete", ) expect(completeCalls).toHaveLength(1) + // complete 请求必须带上 file_size,否则后端同名兜底会误杀同名新视频 + expect(completeCalls[0][1]).toMatchObject({ file_size: file.size }) XMLHttpRequest.prototype.open = origOpen XMLHttpRequest.prototype.send = origSend if (origSetReadyState) {