@opengis/fastify-table
Version:
core-plugins
165 lines (127 loc) • 5.03 kB
JavaScript
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,
},
};
}