diff --git a/src/app/admin/uploads/[uploadPath]/page.tsx b/src/app/admin/uploads/[uploadPath]/page.tsx index dd9a1a2f..2481ddbb 100644 --- a/src/app/admin/uploads/[uploadPath]/page.tsx +++ b/src/app/admin/uploads/[uploadPath]/page.tsx @@ -8,6 +8,7 @@ import { AI_TEXT_GENERATION_ENABLED, BLUR_ENABLED, } from '@/site/config'; +import ErrorNote from '@/components/ErrorNote'; export const maxDuration = 60; @@ -23,16 +24,19 @@ export default async function UploadPage({ params }: Params) { photoFormExif, imageResizedBase64: imageThumbnailBase64, shouldStripGpsData, + error, } = await extractImageDataFromBlobPath(uploadPath, { includeInitialPhotoFields: true, generateBlurData: BLUR_ENABLED, generateResizedImage: AI_TEXT_GENERATION_ENABLED, }); - if ( + const isDataMissing = !photoFormExif || - (AI_TEXT_GENERATION_ENABLED && !imageThumbnailBase64) - ) { + (AI_TEXT_GENERATION_ENABLED && !imageThumbnailBase64); + + if (isDataMissing && !error) { + // Only redirect if there's no error to report redirect(PATH_ADMIN); } @@ -43,14 +47,18 @@ export default async function UploadPage({ params }: Params) { const textFieldsToAutoGenerate = AI_TEXT_AUTO_GENERATED_FIELDS; return ( - + !isDataMissing + ? + : + {error ?? 'Unknown error'} + ); }; diff --git a/src/photo/server.ts b/src/photo/server.ts index 6096da28..3708395a 100644 --- a/src/photo/server.ts +++ b/src/photo/server.ts @@ -29,6 +29,7 @@ export const extractImageDataFromBlobPath = async ( imageResizedBase64?: string shouldStripGpsData?: boolean fileBytes?: ArrayBuffer + error?: string }> => { const { includeInitialPhotoFields, @@ -42,49 +43,60 @@ export const extractImageDataFromBlobPath = async ( const extension = getExtensionFromStorageUrl(url); - const fileBytes = blobPath - ? await fetch(url, { cache: 'no-store' }).then(res => res.arrayBuffer()) - : undefined; - let exifData: ExifData | undefined; let filmSimulation: FilmSimulation | undefined; let blurData: string | undefined; let imageResizedBase64: string | undefined; let shouldStripGpsData = false; + let error: string | undefined; - if (fileBytes) { - const parser = ExifParserFactory.create(Buffer.from(fileBytes)); + const fileBytes = blobPath + ? await fetch(url, { cache: 'no-store' }).then(res => res.arrayBuffer()) + .catch(e => { + error = `Error fetching image from ${url}: "${e.message}"`; + return undefined; + }) + : undefined; - // Data for form - parser.enableBinaryFields(false); - exifData = parser.parse(); + try { + if (fileBytes) { + const parser = ExifParserFactory.create(Buffer.from(fileBytes)); - // Capture film simulation for Fujifilm cameras - if (isExifForFujifilm(exifData)) { - // Parse exif data again with binary fields - // in order to access MakerNote tag - parser.enableBinaryFields(true); - const exifDataBinary = parser.parse(); - const makerNote = exifDataBinary.tags?.MakerNote; - if (Buffer.isBuffer(makerNote)) { - filmSimulation = getFujifilmSimulationFromMakerNote(makerNote); + // Data for form + parser.enableBinaryFields(false); + exifData = parser.parse(); + + // Capture film simulation for Fujifilm cameras + if (isExifForFujifilm(exifData)) { + // Parse exif data again with binary fields + // in order to access MakerNote tag + parser.enableBinaryFields(true); + const exifDataBinary = parser.parse(); + const makerNote = exifDataBinary.tags?.MakerNote; + if (Buffer.isBuffer(makerNote)) { + filmSimulation = getFujifilmSimulationFromMakerNote(makerNote); + } } - } - if (generateBlurData) { - blurData = await blurImage(fileBytes); - } + if (generateBlurData) { + blurData = await blurImage(fileBytes); + } - if (generateResizedImage) { - imageResizedBase64 = await resizeImage(fileBytes); - } + if (generateResizedImage) { + imageResizedBase64 = await resizeImage(fileBytes); + } - shouldStripGpsData = GEO_PRIVACY_ENABLED && ( - Boolean(exifData.tags?.GPSLatitude) || - Boolean(exifData.tags?.GPSLongitude) - ); + shouldStripGpsData = GEO_PRIVACY_ENABLED && ( + Boolean(exifData.tags?.GPSLatitude) || + Boolean(exifData.tags?.GPSLongitude) + ); + } + } catch (e) { + error = `Error extracting image data from ${url}: "${e}"`; } + if (error) { console.log(error); } + return { blobId, ...exifData && { @@ -102,6 +114,7 @@ export const extractImageDataFromBlobPath = async ( imageResizedBase64, shouldStripGpsData, fileBytes, + error, }; };