Skip to content

Instantly share code, notes, and snippets.

@devotox
Last active January 21, 2021 00:09
Show Gist options
  • Save devotox/3618d34e8c870eff8a5cf4d35e0685f0 to your computer and use it in GitHub Desktop.
Save devotox/3618d34e8c870eff8a5cf4d35e0685f0 to your computer and use it in GitHub Desktop.
Run Through S3 Images (JPEG) and optimize them using imagemin and reupload to same path - Automatically sets the cache control to a day and public
#!/usr/bin/node
const fs = require('fs');
const path = require('path');
const AWS = require('aws-sdk');
const Promise = require('bluebird');
const imagemin = require('imagemin');
const imageminJpegRecompress = require('imagemin-jpeg-recompress');
const config = {
sslEnabled: true,
bucket: process.env.AWS_BUCKET,
region: process.env.AWS_REGION,
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
};
AWS.config.update(config);
const s3Bucket = config.bucket;
const s3Endpoint = 's3.' + config.region + '.amazonaws.com';
const s3PublicEndpoint = 'https://' + config.bucket + '.s3.amazonaws.com/';
const s3 = new AWS.S3({ signatureVersion: 'v4', endpoint: s3Endpoint });
const optimizeImage = (image) => {
let imageminOptions = {
plugins: [
imageminJpegRecompress({
progressive: true,
quality: 'high',
accuracy: true,
target: 0.995,
min: 60,
max: 95
})
]
};
return imagemin.buffer(image.Body, imageminOptions)
.then((buffer) => {
console.info('Optimizing Image Finished:', image.Key);
console.log('Prev Size', Math.round(image.Body.toString().length / 1000) + 'KB');
console.log('New Size', Math.round(buffer.toString().length / 1000) + 'KB\n');
return { Body: buffer, Key: image.Key };
})
.catch((error) => {
console.error('Image Optimization Error:', image.Key, error);
});
};
const listImages = (params) => {
return new Promise((resolve, reject) => {
s3.listObjects(params, (error, images) => {
return error ? reject(error) : resolve(images);
});
});
};
const getImage = (image) => {
let params = { Bucket: config.bucket, Key: image.Key };
return new Promise((resolve, reject) => {
s3.getObject(params, (error, image) => {
image ? image.Key = params.Key : null;
return error ? reject(error) : resolve(image);
});
});
};
const setImage = (image) => {
if(!(image && image.Key && image.Body)) {
return Promise.resolve();
}
let params = {
Body: image.Body,
Key: image.Key,
Bucket: config.bucket,
ACL: "public-read",
ContentType: "image/jpeg",
CacheControl: "max-age=86400, public"
};
return new Promise((resolve, reject) => {
s3.putObject(params, (error) => {
console.log('\nUploaded', params.Key, error ? error : '');
return error ? reject(error) : resolve();
});
});
};
const optimize = (image) => {
return getImage(image)
.then(optimizeImage)
.then(setImage)
.catch(console.error);
};
const run = (Marker, oneRun) => {
let params = { Bucket: config.bucket, MaxKeys: oneRun ? 1 : 100 };
params.Marker = Marker;
console.log('\nNext Marker', Marker);
return listImages(params)
.then((data) => {
console.log('\nTotal Length:', data.Contents.length);
return Promise.map(data.Contents, optimize)
.then(() => data.IsTruncated && !oneRun ? run(data.Contents.slice(-1)[0].Key) : null);
});
};
return run(process.argv[2], process.argv[3]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment