83 lines
2.0 KiB
TypeScript
83 lines
2.0 KiB
TypeScript
// worker/process-image.ts
|
|
import sharp from "sharp";
|
|
import { getMinioClient } from "./minio";
|
|
import { lookup } from "mime-types";
|
|
|
|
export async function processImage(
|
|
bucket: string,
|
|
key: string
|
|
): Promise<boolean> {
|
|
const minio = getMinioClient();
|
|
|
|
const stat = await minio.statObject(bucket, key);
|
|
const meta = stat as unknown as { metaData: Record<string, string> };
|
|
|
|
const mime = meta.metaData["content-type"] || lookup(key) || "";
|
|
|
|
if (!mime.startsWith("image/")) {
|
|
console.log(`⏭️ Skipping non-image file: ${key}`);
|
|
return false;
|
|
}
|
|
|
|
if (
|
|
meta.metaData["x-amz-meta-processed"] === "true" ||
|
|
meta.metaData["processed"] === "true"
|
|
) {
|
|
console.log(`♻️ Already processed: ${key}`);
|
|
return false;
|
|
}
|
|
|
|
const stream = await minio.getObject(bucket, key);
|
|
const chunks: Buffer[] = [];
|
|
for await (const chunk of stream) chunks.push(chunk);
|
|
const buffer = Buffer.concat(chunks);
|
|
|
|
const fileName = key.split("/").pop();
|
|
const filePath = key.substring(0, key.lastIndexOf("/"));
|
|
|
|
const thumb = await sharp(buffer).resize(200).toBuffer();
|
|
await minio.putObject(
|
|
bucket,
|
|
`${filePath}/thumbs/${fileName}`,
|
|
thumb,
|
|
thumb.length,
|
|
{
|
|
"Content-Type": mime,
|
|
"x-amz-meta-processed": "true",
|
|
}
|
|
);
|
|
|
|
const optimized = await sharp(buffer).jpeg({ quality: 80 }).toBuffer();
|
|
await minio.putObject(
|
|
bucket,
|
|
`${filePath}/optimized/${fileName}`,
|
|
optimized,
|
|
optimized.length,
|
|
{
|
|
"Content-Type": mime,
|
|
"x-amz-meta-processed": "true",
|
|
}
|
|
);
|
|
|
|
const webp = await sharp(buffer).webp({ quality: 80 }).toBuffer();
|
|
await minio.putObject(
|
|
bucket,
|
|
`${filePath}/webp/${fileName?.replace(/\.[^/.]+$/, ".webp")}`,
|
|
webp,
|
|
webp.length,
|
|
{
|
|
"Content-Type": "image/webp",
|
|
"x-amz-meta-processed": "true",
|
|
}
|
|
);
|
|
|
|
// Re-upload original object with metadata
|
|
await minio.putObject(bucket, key, buffer, buffer.length, {
|
|
"Content-Type": mime,
|
|
"x-amz-meta-processed": "true",
|
|
});
|
|
|
|
console.log(`✅ Processed image: ${key}`);
|
|
return true;
|
|
}
|