@opengis/fastify-table
Version:
core-plugins
144 lines (143 loc) • 5.52 kB
JavaScript
/* eslint-disable no-console */
import { imageSize } from "image-size";
import { pgClients, eventStream, logger, isFileExists, downloadFile, uploadFile, } from "../../../../utils.js";
import grpc from "../../../plugins/grpc/grpc.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 = () => { }, }) {
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}`);
const unittest = process.env.NODE_ENV === "test" || process.env.VITEST;
// 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 = {} } = 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 = process.env.NODE_ENV === "test" || process.env.VITEST
? 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,
})), 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,
},
};
}