From 2b131f76c1c0e25a8ead58ef2ad1bde5dd0fac6d Mon Sep 17 00:00:00 2001 From: Maksim Eltyshev Date: Sat, 24 Dec 2022 16:24:50 +0100 Subject: [PATCH] fix: Proper image error handling during migration --- ...1625_preserve_original_format_of_images.js | 83 ++++++++++--------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/server/db/migrations/20221223131625_preserve_original_format_of_images.js b/server/db/migrations/20221223131625_preserve_original_format_of_images.js index 6d53eb25f..de2ec07cd 100644 --- a/server/db/migrations/20221223131625_preserve_original_format_of_images.js +++ b/server/db/migrations/20221223131625_preserve_original_format_of_images.js @@ -42,58 +42,65 @@ const rollbackImage = async (knex, tableName, fieldName, prevFieldName) => { }); }; -module.exports.up = async (knex) => { - await migrateImage(knex, 'user_account', 'avatar', 'avatar_dirname'); - await migrateImage(knex, 'project', 'background_image', 'background_image_dirname'); +const processAttachmentImage = async (attachment, attachmentsPath) => { + const rootPath = path.join(attachmentsPath, attachment.dirname); + const thumbnailsPath = path.join(rootPath, 'thumbnails'); - const config = await getConfig(); - const attachments = await knex('attachment').whereNotNull('image'); + const image = sharp(path.join(rootPath, attachment.filename), { + animated: true, + }); - // eslint-disable-next-line no-restricted-syntax - for (attachment of attachments) { - const rootPath = path.join(config.custom.attachmentsPath, attachment.dirname); - const thumbnailsPath = path.join(rootPath, 'thumbnails'); + let metadata; + try { + metadata = await image.metadata(); + } catch (error) { + return null; + } - const image = sharp(path.join(rootPath, attachment.filename), { - animated: true, - }); + const { width, pageHeight: height = metadata.height } = metadata; + const thumbnailsExtension = metadata.format === 'jpeg' ? 'jpg' : metadata.format; - let metadata; + try { + await image + .resize(256, height > width ? 320 : undefined, { + kernel: sharp.kernel.nearest, + }) + .toFile(path.join(thumbnailsPath, `cover-256.${thumbnailsExtension}`)); + } catch (error) { + return null; + } + + if (thumbnailsExtension !== 'jpg') { try { - metadata = await image.metadata(); // eslint-disable-line no-await-in-loop + rimraf.sync(path.join(thumbnailsPath, 'cover-256.jpg')); } catch (error) { - continue; // eslint-disable-line no-continue + console.warn(error.stack); // eslint-disable-line no-console } + } - const extension = metadata.format === 'jpeg' ? 'jpg' : metadata.format; + return { + width, + height, + thumbnailsExtension, + }; +}; - try { - // eslint-disable-next-line no-await-in-loop - await image - .resize(256, metadata.height > metadata.width ? 320 : undefined, { - kernel: sharp.kernel.nearest, - }) - .toFile(path.join(thumbnailsPath, `cover-256.${extension}`)); - } catch (error) { - continue; // eslint-disable-line no-continue - } +module.exports.up = async (knex) => { + await migrateImage(knex, 'user_account', 'avatar', 'avatar_dirname'); + await migrateImage(knex, 'project', 'background_image', 'background_image_dirname'); - if (extension !== 'jpg') { - try { - rimraf.sync(path.join(thumbnailsPath, 'cover-256.jpg')); - } catch (error) { - console.warn(error.stack); // eslint-disable-line no-console - } - } + const config = await getConfig(); + const attachments = await knex('attachment').whereNotNull('image'); + + // eslint-disable-next-line no-restricted-syntax + for (attachment of attachments) { + // eslint-disable-next-line no-await-in-loop + const image = await processAttachmentImage(attachment, config.custom.attachmentsPath); // eslint-disable-next-line no-await-in-loop await knex('attachment') .update({ - image: { - width: metadata.width, - height: metadata.pageHeight || metadata.height, - thumbnailsExtension: extension, - }, + image: image || knex.raw('?? || \'{"thumbnailsExtension":"jpg"}\'', ['image']), }) .where('id', attachment.id); }