diff --git a/src/image-response/components/ImagePhotoGrid.tsx b/src/image-response/components/ImagePhotoGrid.tsx index d523e19c..0b8abd97 100644 --- a/src/image-response/components/ImagePhotoGrid.tsx +++ b/src/image-response/components/ImagePhotoGrid.tsx @@ -3,7 +3,7 @@ import { Photo } from '@/photo'; import { NextImageSize } from '@/platforms/next-image'; import { IS_PREVIEW } from '@/app/config'; -import { getOptimizedUrlsForPhotos } from '@/photo/storage'; +import { getDataUrlsForPhotos } from '@/photo/storage'; export default async function ImagePhotoGrid({ photos, @@ -52,7 +52,7 @@ export default async function ImagePhotoGrid({ const cellHeight= height / rows - (rows - 1) * gap / rows; - const photoUrls = await getOptimizedUrlsForPhotos( + const photoUrls = await getDataUrlsForPhotos( photos, optimizedSuffix, nextImageWidth, @@ -60,7 +60,7 @@ export default async function ImagePhotoGrid({ ); const renderPhoto = ( - { id, url }: typeof photoUrls[number], + { id, urlData }: typeof photoUrls[number], width: number, height: number, ) => @@ -75,7 +75,7 @@ export default async function ImagePhotoGrid({ }} > { ); }; -export const getOptimizedUrlsForPhotos = async ( +export const getDataUrlsForPhotos = async ( photos: Photo[], optimizedSuffix: OptimizedSuffix, nextImageWidth: NextImageSize, addBypassSecret: boolean, ) => Promise.all(photos - .map(async({ id, url: _url }) => { + .map(async({ id, url }) => { // Check for optimized image first const optimizedUrl =await getSignedUrlForUrl( - getOptimizedPhotoUrlForSuffix(_url, optimizedSuffix), + getOptimizedPhotoUrlForSuffix(url, optimizedSuffix), 'GET', ); - const optimizedUrlExists = await fetch(optimizedUrl) - .then(res => res.ok) - .catch(() => false); + const optimizedUrlData = await fetchBase64ImageFromUrl(optimizedUrl); - if (optimizedUrlExists) { - return { id, url: optimizedUrl }; + if (optimizedUrlData) { + return { id, urlData: optimizedUrlData }; } else { // Fall back on `next/image` if optimized image is not available const nextImageUrl = getOptimizedPhotoUrl({ - imageUrl: _url, + imageUrl: url, size: nextImageWidth, addBypassSecret, }); - const nextImageUrlExists = await fetch(nextImageUrl) - .then(res => res.ok) - .catch(() => false); - return { id, url: nextImageUrlExists ? nextImageUrl : undefined }; + const nextImageUrlData = await fetchBase64ImageFromUrl(nextImageUrl); + return { id, urlData: nextImageUrlData }; } })) - .then(urls =>(urls.every(url => Boolean(url)) + .then(urls =>(urls.every(({ urlData }) => Boolean(urlData)) ? urls - // If any url is defined, return an empty array - : []) as { id: string, url: string }[]); + // If any url is undefined, return an empty array + : []) as { id: string, urlData: string }[]); diff --git a/src/utility/image.ts b/src/utility/image.ts index 56715297..167879f9 100644 --- a/src/utility/image.ts +++ b/src/utility/image.ts @@ -1,15 +1,24 @@ +import { getFileNamePartsFromStorageUrl } from '@/platforms/storage'; + export const removeBase64Prefix = (base64: string) => { return base64.match(/^data:image\/[a-z]{3,4};base64,(.+)$/)?.[1] ?? base64; }; -export const fetchBase64ImageFromUrl = ( +export const fetchBase64ImageFromUrl = async ( url: string, - contentType?: string, fetchOptions?: RequestInit, -) => - fetch(url, fetchOptions) +) => { + const { fileExtension } = getFileNamePartsFromStorageUrl(url); + const contentType = fileExtension === 'png' ? 'image/png' : 'image/jpeg'; + return fetch(url, fetchOptions) .then(async response => { - const blob = await response.arrayBuffer(); - // eslint-disable-next-line max-len - return `data:${contentType ?? response.headers.get('content-type')};base64,${Buffer.from(blob).toString('base64')}`; - }); + if (response.ok) { + const blob = await response.arrayBuffer(); + // eslint-disable-next-line max-len + return `data:${contentType};base64,${Buffer.from(blob).toString('base64')}`; + } else { + return undefined; + } + }) + .catch(() => undefined); +};