107 lines
2.8 KiB
JavaScript
107 lines
2.8 KiB
JavaScript
|
import { Client } from "minio";
|
||
|
import sharp from "sharp"
|
||
|
import {config} from "dotenv"
|
||
|
config()
|
||
|
|
||
|
// Retrieve MinIO details from environment variables
|
||
|
const minioEndpoint = process.env["S3_ENDPOINT_URL"] || "your-minio-endpoint";
|
||
|
const minioAccessKey = process.env["S3_ACCESS_KEY"] || "your-access-key";
|
||
|
const minioSecretKey = process.env["S3_SECRET_ACCESS_KEY"] || "your-secret-key";
|
||
|
const minioBucketName = "silvester23";
|
||
|
|
||
|
const minioClient = new Client({
|
||
|
endPoint: minioEndpoint,
|
||
|
accessKey: minioAccessKey,
|
||
|
secretKey: minioSecretKey,
|
||
|
});
|
||
|
|
||
|
|
||
|
const objects = [];
|
||
|
|
||
|
const objectStream = minioClient.listObjects(minioBucketName);
|
||
|
|
||
|
for await (const obj of objectStream) {
|
||
|
objects.push(obj);
|
||
|
}
|
||
|
|
||
|
async function compressObject(pngBuffer, fileName, format) {
|
||
|
|
||
|
const newFilePath = `${fileName.slice(0, -4)}.${format}`;
|
||
|
|
||
|
let buffer;
|
||
|
switch (format) {
|
||
|
case "webp":
|
||
|
buffer = await sharp(pngBuffer).webp({ quality: 80 }).toBuffer();
|
||
|
break;
|
||
|
case "jpg":
|
||
|
buffer = await sharp(pngBuffer).jpeg({ quality: 80 }).toBuffer();
|
||
|
break;
|
||
|
case "avif":
|
||
|
buffer = await sharp(pngBuffer).avif({ quality: 80 }).toBuffer();
|
||
|
break;
|
||
|
default:
|
||
|
throw new Error(`Unknown format ${format}`);
|
||
|
}
|
||
|
|
||
|
// Upload the JPG buffer back to the same MinIO bucket
|
||
|
await minioClient.putObject(minioBucketName, newFilePath, buffer, {
|
||
|
'Content-Type': 'image/' + format,
|
||
|
});
|
||
|
|
||
|
console.log(`Uploaded ${newFilePath} to MinIO`);
|
||
|
}
|
||
|
|
||
|
async function fetchBuffer(objectName) {
|
||
|
const chunks = [];
|
||
|
|
||
|
return new Promise((res, rej) => {
|
||
|
minioClient.getObject(minioBucketName,objectName, function (err, dataStream) {
|
||
|
if (err) {
|
||
|
return console.log(err)
|
||
|
}
|
||
|
dataStream.on('data', function (chunk) {
|
||
|
chunks.push(chunk);
|
||
|
})
|
||
|
dataStream.on('end', function () {
|
||
|
res(Buffer.concat(chunks))
|
||
|
})
|
||
|
dataStream.on('error', function (err) {
|
||
|
console.log(err)
|
||
|
rej(err)
|
||
|
})
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
|
||
|
const pngs = objects.filter((o) => o.name.endsWith(".png"));
|
||
|
console.log(`Found ${pngs.length} PNGs`);
|
||
|
|
||
|
for (const obj of pngs) {
|
||
|
const pngFilePath = obj.name;
|
||
|
const jpgFilePath = pngFilePath.slice(0, -4) + ".jpg";
|
||
|
const avifFilePath = pngFilePath.slice(0, -4) + ".avif";
|
||
|
const webpFilePath = pngFilePath.slice(0, -4) + ".webp";
|
||
|
|
||
|
const hasJpg = objects.some((o) => o.name === jpgFilePath);
|
||
|
const hasAvif = objects.some((o) => o.name === avifFilePath);
|
||
|
const hasWebp = objects.some((o) => o.name === webpFilePath);
|
||
|
|
||
|
if(hasAvif && hasJpg && hasWebp) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
const pngBuffer = await fetchBuffer(pngFilePath);
|
||
|
|
||
|
if(!hasJpg) {
|
||
|
await compressObject(pngBuffer, pngFilePath, "jpg");
|
||
|
}
|
||
|
|
||
|
if(!hasAvif) {
|
||
|
await compressObject(pngBuffer, pngFilePath, "avif");
|
||
|
}
|
||
|
if(!hasWebp) {
|
||
|
await compressObject(pngBuffer, pngFilePath, "webp");
|
||
|
}
|
||
|
|
||
|
}
|