diff --git a/src/lib/modules/thumbnail.ts b/src/lib/modules/thumbnail.ts index 9c009bd..2d5cd55 100644 --- a/src/lib/modules/thumbnail.ts +++ b/src/lib/modules/thumbnail.ts @@ -32,7 +32,7 @@ const capture = ( drawer(context, scaledWidth, scaledHeight); canvas.toBlob((blob) => { - if (blob) { + if (blob && blob.type === "image/webp") { resolve(blob); } else { reject(new Error("Failed to generate thumbnail")); @@ -83,18 +83,26 @@ const generateVideoThumbnail = (videoUrl: string, time = 0) => { export const generateThumbnail = async (fileBuffer: ArrayBuffer, fileType: string) => { let url; try { - if (fileType === "image/heic") { - const { default: heic2any } = await import("heic2any"); - url = URL.createObjectURL( - (await heic2any({ - blob: new Blob([fileBuffer], { type: fileType }), - toType: "image/png", - })) as Blob, - ); - return await generateImageThumbnail(url); - } else if (fileType.startsWith("image/")) { - url = URL.createObjectURL(new Blob([fileBuffer], { type: fileType })); - return await generateImageThumbnail(url); + if (fileType.startsWith("image/")) { + const fileBlob = new Blob([fileBuffer], { type: fileType }); + url = URL.createObjectURL(fileBlob); + + try { + return await generateImageThumbnail(url); + } catch { + URL.revokeObjectURL(url); + url = undefined; + + if (fileType === "image/heic") { + const { default: heic2any } = await import("heic2any"); + url = URL.createObjectURL( + (await heic2any({ blob: fileBlob, toType: "image/png" })) as Blob, + ); + return await generateImageThumbnail(url); + } else { + return null; + } + } } else if (fileType.startsWith("video/")) { url = URL.createObjectURL(new Blob([fileBuffer], { type: fileType })); return await generateVideoThumbnail(url); diff --git a/src/routes/(fullscreen)/file/[id]/+page.svelte b/src/routes/(fullscreen)/file/[id]/+page.svelte index 61465bd..4047e7c 100644 --- a/src/routes/(fullscreen)/file/[id]/+page.svelte +++ b/src/routes/(fullscreen)/file/[id]/+page.svelte @@ -43,22 +43,31 @@ let isDownloadRequested = $state(false); let viewerType: "image" | "video" | undefined = $state(); let fileBlobUrl: string | undefined = $state(); + let heicBlob: Blob | undefined = $state(); let videoElement: HTMLVideoElement | undefined = $state(); const updateViewer = async (buffer: ArrayBuffer, contentType: string) => { const fileBlob = new Blob([buffer], { type: contentType }); - if (contentType === "image/heic") { - const { default: heic2any } = await import("heic2any"); - fileBlobUrl = URL.createObjectURL( - (await heic2any({ blob: fileBlob, toType: "image/jpeg" })) as Blob, - ); - } else if (viewerType) { + if (viewerType) { fileBlobUrl = URL.createObjectURL(fileBlob); + heicBlob = contentType === "image/heic" ? fileBlob : undefined; } - return fileBlob; }; + const convertHeicToJpeg = async () => { + if (!heicBlob) return; + + URL.revokeObjectURL(fileBlobUrl!); + fileBlobUrl = undefined; + + const { default: heic2any } = await import("heic2any"); + fileBlobUrl = URL.createObjectURL( + (await heic2any({ blob: heicBlob, toType: "image/jpeg" })) as Blob, + ); + heicBlob = undefined; + }; + const updateThumbnail = async (dataKey: CryptoKey, dataKeyVersion: Date) => { const thumbnail = await captureVideoThumbnail(videoElement!); await requestThumbnailUpload(data.id, thumbnail, dataKey, dataKeyVersion); @@ -136,7 +145,7 @@ {#if viewerType === "image"} {#if fileBlobUrl} - {$info.name} + {$info.name} {:else} {@render viewerLoading("이미지를 불러오고 있어요.")} {/if}