diff --git a/src/api/aiGenerationClient.ts b/src/api/aiGenerationClient.ts index f580b5a..032ef9f 100644 --- a/src/api/aiGenerationClient.ts +++ b/src/api/aiGenerationClient.ts @@ -403,6 +403,22 @@ export const aiGenerationClient = { return readJsonResponse<{ url: string; ossKey?: string }>(res, "Asset upload response failed"); }, + async uploadAssetBinary(blob: Blob, options?: { name?: string; mimeType?: string; scope?: string }): Promise<{ url: string; signedUrl?: string; ossKey?: string }> { + const form = new FormData(); + form.append("file", blob, options?.name || "upload.png"); + if (options?.scope) form.append("scope", options.scope); + if (options?.mimeType) form.append("mimeType", options.mimeType); + const res = await fetch(buildApiUrl("oss/upload-binary"), { + method: "POST", + headers: { ...buildAuthHeaders() }, + body: form, + }); + if (!res.ok) { + await throwResponseError(res, "Binary asset upload failed"); + } + return readJsonResponse<{ url: string; ossKey?: string }>(res, "Binary asset upload response failed"); + }, + async uploadAssetByUrl(input: UploadAssetByUrlInput): Promise<{ url: string; signedUrl?: string; ossKey?: string }> { const res = await fetch(buildApiUrl("oss/upload-by-url"), { method: "POST", diff --git a/src/features/ecommerce/EcommercePage.tsx b/src/features/ecommerce/EcommercePage.tsx index 9774b8a..3c500ba 100644 --- a/src/features/ecommerce/EcommercePage.tsx +++ b/src/features/ecommerce/EcommercePage.tsx @@ -1326,15 +1326,10 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { for (const item of productImages) { try { const resp = await fetch(item.src); - const blob = await resp.blob(); - const mimeType = SUPPORTED_IMAGE_TYPES.has(blob.type) ? blob.type : "image/png"; - const dataUrl = await new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.onload = () => resolve(String(reader.result)); - reader.onerror = () => reject(reader.error); - reader.readAsDataURL(blob); - }); - const { url } = await aiGenerationClient.uploadAsset({ dataUrl, name: item.name, mimeType }); + const rawBlob = await resp.blob(); + const mimeType = SUPPORTED_IMAGE_TYPES.has(rawBlob.type) ? rawBlob.type : "image/png"; + const blob = rawBlob.type === mimeType ? rawBlob : new Blob([rawBlob], { type: mimeType }); + const { url } = await aiGenerationClient.uploadAssetBinary(blob, { name: item.name, mimeType, scope: "ecommerce-product" }); urls.push(url); } catch { // skip images that fail to upload