UNPKG

@opengis/fastify-table

Version:

core-plugins

165 lines (127 loc) 5.03 kB
import { imageSize } from 'image-size'; import { pgClients, eventStream, logger, isFileExists, downloadFile, uploadFile, grpc, } from '../../../../utils.js'; import { images } from '../../../plugins/file/utils/allowedExtensions.js'; const { resizeImage } = grpc(); async function resizeOne({ relpath: relpath1, resizeQuality = 80, maxWidth = 2048, errors = [], success = [], notfound = [], equalwidth = [], send = () => { }, unittest, }) { const exists = await isFileExists(relpath1); const existsOriginal = await isFileExists(relpath1.replace('files/', 'files/original/')); const relpath = existsOriginal ? relpath1.replace('files/', 'files/original/') : relpath1; const buffer = (exists || existsOriginal) ? await downloadFile(relpath, { buffer: true }) : null; if (!buffer?.length) { notfound.push(relpath1); send(`file not found: ${relpath1}`); return null; } if (!existsOriginal) { await uploadFile(relpath1.replace('files/', 'files/original/'), buffer); send(`original image moved to: ${relpath1.replace('files/', 'files/original/')}`); } else { send(`original image already saved to: ${relpath}`); } const dimensions = {}; try { const { width, height } = imageSize(buffer) || {}; Object.assign(dimensions, { width, height }); } catch (err) { // handle broken image (callback w/ buffer input not supported) errors.push(relpath1); send(`${err.toString()}: ${relpath1} (${buffer?.length} - ${exists.ContentType})`); return null; } const { width = maxWidth, height = 240 } = dimensions; const ratio = width / height; const resizeWidth = Math.min(width, maxWidth); const resizeHeight = resizeWidth / ratio; send(`original ${relpath} width/height/ratio: ${width} / ${height} / ${ratio}`); send(`resize ${relpath} width/height/ratio/quality: ${resizeWidth} / ${resizeHeight} / ${resizeWidth / resizeHeight} / ${resizeQuality}`); // skip for resize with small unit test image if (resizeWidth === width && !unittest) { send(`resize ${relpath} skip: resize width equals to original`); equalwidth.push(relpath1); return null; } const { result } = await resizeImage({ base64: buffer.toString('base64'), width: resizeWidth, height: resizeHeight, quality: resizeQuality, }); await uploadFile(relpath1, Buffer.from(result, 'base64')); send(`resize ${relpath1} success`); success.push(relpath1); return null; } export default async function resizeAll(req, reply) { const { pg = pgClients.client, query = {}, unittest } = req; const { nocache, filepath, quality = 80, limit, sql, w = 2048, } = query; if (nocache) { const clearQ = `update crm.files set resized=null where ext=any($1) and ${filepath ? 'file_path=$2' : '1=1'} and resized is not null`; if (sql) return clearQ; const { rowCount = 0 } = await pg.query(clearQ, [images, filepath].filter(Boolean)); return reply.status(200).send({ msg: 'clear cache success', rowCount }); } const resizeQuality = Math.min(quality, 100); const q = `select file_id as id, file_path as relpath from crm.files where ext=any($1) and ${filepath ? 'file_path=$2' : '1=1'} and resized is null ${limit ? `limit ${limit}` : ''}`; if (sql) return q; const { rows = [], rowCount = 0 } = await pg.query(q, [images, filepath].filter(Boolean)); if (rowCount === 0) { return reply.status(200).send('nothing to resize'); } const success = []; const errors = []; const notfound = []; const equalwidth = []; const send = unittest ? console.log : eventStream(reply); try { send(`file max resize width: ${w}`); send(`file max resize quality: ${resizeQuality}`); send(`rows found: ${rowCount}`); await rows .filter((el, idx, array) => array.findIndex(item => item.relpath === el.relpath) === idx) .reduce((promise, { relpath, id }) => promise.then(() => resizeOne({ relpath, id, resizeQuality, maxWidth: w, errors, success, notfound, equalwidth, send, unittest, })), Promise.resolve()); if (success.length) { await pg.query('update crm.files set resized=true where file_path=any($1::text[])', [success]); } const skip = errors.concat(notfound).concat(equalwidth); if (skip.length) { await pg.query('update crm.files set resized=false where file_path=any($1::text[])', [skip]); } logger.file('file/resize', { success, errors, notfound, equalwidth, }); send('resize all success'); } catch (err) { send(err.toString()); logger.file('file/resize', { error: err.toString(), stack: err.stack }); } finally { send('event stream finish', 1); } return { success, errors, notfound, equalwidth, options: { maxWidth: w, quality: resizeQuality, }, }; }