diff --git a/packages/frontend/core/package.json b/packages/frontend/core/package.json index 850c2c8c39..ffa98804e6 100644 --- a/packages/frontend/core/package.json +++ b/packages/frontend/core/package.json @@ -47,6 +47,7 @@ "@react-hookz/web": "^24.0.4", "@sentry/integrations": "^7.109.0", "@sentry/react": "^8.0.0", + "@sgtpooki/file-type": "^1.0.1", "@toeverything/theme": "^0.7.35", "@vanilla-extract/dynamic": "^2.1.0", "animejs": "^3.2.2", diff --git a/packages/frontend/core/src/modules/peek-view/view/image-preview/index.tsx b/packages/frontend/core/src/modules/peek-view/view/image-preview/index.tsx index 41e8ae47e9..ea9a7d4243 100644 --- a/packages/frontend/core/src/modules/peek-view/view/image-preview/index.tsx +++ b/packages/frontend/core/src/modules/peek-view/view/image-preview/index.tsx @@ -16,6 +16,7 @@ import { ViewBarIcon, } from '@blocksuite/icons/rc'; import type { BlockModel } from '@blocksuite/store'; +import { fileTypeFromBuffer } from '@sgtpooki/file-type'; import { useService } from '@toeverything/infra'; import clsx from 'clsx'; import { useErrorBoundary } from 'foxact/use-error-boundary'; @@ -41,35 +42,6 @@ const filterImageBlock = (block: BlockModel): block is ImageBlockModel => { return block.flavour === 'affine:image'; }; -function resolveMimeType(buffer: Uint8Array): string { - if ( - buffer[0] === 0x47 && - buffer[1] === 0x49 && - buffer[2] === 0x46 && - buffer[3] === 0x38 - ) { - return 'image/gif'; - } else if ( - buffer[0] === 0x89 && - buffer[1] === 0x50 && - buffer[2] === 0x4e && - buffer[3] === 0x47 - ) { - return 'image/png'; - } else if ( - buffer[0] === 0xff && - buffer[1] === 0xd8 && - buffer[2] === 0xff && - buffer[3] === 0xe0 - ) { - return 'image/jpeg'; - } else { - // unknown, fallback to png - console.error('unknown image type'); - return 'image/png'; - } -} - async function imageUrlToBlob(url: string): Promise { const buffer = await fetch(url).then(response => { return response.arrayBuffer(); @@ -80,8 +52,11 @@ async function imageUrlToBlob(url: string): Promise { return; } try { - const type = resolveMimeType(new Uint8Array(buffer)); - const blob = new Blob([buffer], { type }); + const type = await fileTypeFromBuffer(buffer); + if (!type) { + return; + } + const blob = new Blob([buffer], { type: type.mime }); return blob; } catch (error) { console.error('Error converting image to blob', error); diff --git a/yarn.lock b/yarn.lock index a3d9a86bf9..13a9545f85 100644 --- a/yarn.lock +++ b/yarn.lock @@ -415,6 +415,7 @@ __metadata: "@sentry/integrations": "npm:^7.109.0" "@sentry/react": "npm:^8.0.0" "@sentry/webpack-plugin": "npm:^2.16.1" + "@sgtpooki/file-type": "npm:^1.0.1" "@swc/core": "npm:^1.4.13" "@testing-library/react": "npm:^16.0.0" "@toeverything/theme": "npm:^0.7.35" @@ -13465,7 +13466,7 @@ __metadata: languageName: node linkType: hard -"@sgtpooki/file-type@npm:1.0.1": +"@sgtpooki/file-type@npm:1.0.1, @sgtpooki/file-type@npm:^1.0.1": version: 1.0.1 resolution: "@sgtpooki/file-type@npm:1.0.1" dependencies: