fix(storage): prevent duplicate COS resource uploads
This commit is contained in:
@@ -13,6 +13,8 @@ const store = localforage.createInstance({ name: "infinite-canvas", storeName: "
|
||||
const objectUrls = new Map<string, string>();
|
||||
|
||||
export async function uploadMediaFile(input: string | Blob, prefix = "file"): Promise<UploadedFile> {
|
||||
// 直传和失败后的本地同步必须复用同一上传身份,避免响应丢失后创建第二个对象。
|
||||
const storageKey = `${prefix}:${getActiveUserScope()}:${nanoid()}`;
|
||||
const blob = typeof input === "string" ? await (await fetch(input)).blob() : input;
|
||||
const previewUrl = URL.createObjectURL(blob);
|
||||
const captured = blob.type.startsWith("video/") ? await captureVideoPoster(previewUrl).catch(() => undefined) : undefined;
|
||||
@@ -29,14 +31,13 @@ export async function uploadMediaFile(input: string | Blob, prefix = "file"): Pr
|
||||
const poster = captured?.poster ? await uploadImage(captured.poster).catch(() => undefined) : undefined;
|
||||
try {
|
||||
const kind = blob.type.startsWith("video/") ? "video" : blob.type.startsWith("audio/") ? "audio" : "file";
|
||||
const resource = await uploadResourceFile(blob, kind, { ...meta, fileName: input instanceof File ? input.name : undefined });
|
||||
const resource = await uploadResourceFile(blob, kind, { ...meta, fileName: input instanceof File ? input.name : undefined, idempotencyKey: storageKey });
|
||||
await primeResourceBlobCache(resourceStorageKey(resource.id), blob).catch(() => "");
|
||||
URL.revokeObjectURL(previewUrl);
|
||||
return { url: resource.publicUrl || resourceFileUrl(resource.id), storageKey: resourceStorageKey(resource.id), bytes: resource.size || blob.size, mimeType: resource.mimeType || blob.type || "application/octet-stream", width: resource.width || meta.width, height: resource.height || meta.height, durationMs: resource.durationMs || meta.durationMs, hasAudio: meta.hasAudio, preview: poster };
|
||||
} catch {
|
||||
// OSS is optional during local/self-hosted setup. Keep the existing local fallback.
|
||||
}
|
||||
const storageKey = `${prefix}:${getActiveUserScope()}:${nanoid()}`;
|
||||
await store.setItem(storageKey, blob);
|
||||
const url = previewUrl;
|
||||
objectUrls.set(storageKey, url);
|
||||
|
||||
Reference in New Issue
Block a user