Skip to content

Instantly share code, notes, and snippets.

@AntoniusGolly
Created March 18, 2018 17:17
Show Gist options
  • Save AntoniusGolly/eee090526e4140ca34f0aa4ea5d571cc to your computer and use it in GitHub Desktop.
Save AntoniusGolly/eee090526e4140ca34f0aa4ea5d571cc to your computer and use it in GitHub Desktop.
Sample Node.js script for resizing images with the Sharp library
'use strict';
const AWS = require('aws-sdk');
const S3 = new AWS.S3({
signatureVersion: 'v4',
});
const sharp = require('sharp');
const BUCKET = process.env.BUCKET ? process.env.BUCKET : "mybucket";
const URL = process.env.URL ? process.env.URL : "http://localhost:5858"; // for local development
const PRESETS = process.env.PRESETS ? JSON.parse(process.env.PRESETS) : "{}";
exports.handler = function(event, context, callback){
const key = event.queryStringParameters.key;
const ext = key.match(/(?:\.([^.]+))?$/)[1].toLocaleLowerCase();
const format = ext === "png" ? "png" : "jpeg";
const writeKey = key;
let url, preset, resource, dimension, width, height, originalKey = null;
let quality = 80;
let redirect_status = '302';
let redirect_headers = process.env.URL ? {
'location': `${URL}/${key}`
} : {};
/**
*
* This script will resize images based on pre-defined keywords.
*
* Sample request:
*
* <bucket>/resized/full/my_picture.jpg
*
* The script will parse the path to keyword and picture name. The script will look
* for the original resource in <bucket>/original/my_picture.jpg and resize
* according to the dimension of "full". The mapping of the keyword "full" to actual pixel
* dimensions is defined in the environment variable PRESETS.
*
* The script accepts full dimension requests (width and height specified)
* and single dimension requests (just width). If both are provided the image
* will be scaled to this specific dimension. If only width is provided
* the height will be matched accordingly.
*
*/
// get preset (keyword) from URL
if(url = key.match(/^(resized)\/([a-z_]+)\/(.*)/)) {
// URL: resized/full/picture.jpg
// url [1] [2] [3]
preset = url[2]
resource = url[3]
if (preset in PRESETS) {
quality = parseInt(PRESETS[preset].quality);
originalKey = "original/" + resource // path to original image resource
// get dimension from keyword
if (dimension = PRESETS[preset].res.match(/((\d+)x(\d+))/)) {
// if dimension as WIDTH x HEIGHT (560x430)
width = parseInt(dimension[2], 10);
height = parseInt(dimension[3], 10);
} else if (dimension = PRESETS[preset].res.match(/(^(\d+))/)) {
// if dimension as WIDTH ONLY (560)
width = parseInt(dimension[2], 10);
}
} else {
callback(null, {
statusCode: '400',
headers: {},
body: 'Not a valid keyword requested [2].',
});
return;
}
} else {
callback(null, {
statusCode: '400',
headers: {},
body: 'Not a valid keyword requested [1].',
});
return;
}
if(width == null){
callback(null, {
statusCode: '400',
headers: {},
body: 'Not a valid keyword requested [3].',
});
return;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
OUTPUT
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
if(ext === "gif"){
/**
* Pass through *.gif's as it could be animated
*/
// get original key from S3 with Sharp library, resize and put back to S3
S3.getObject({Bucket: BUCKET, Key: originalKey}).promise()
.then(data => S3.putObject({
Body: data.Body,
Bucket: BUCKET,
ContentType: 'image/gif',
Key: writeKey,
}).promise())
.then(() => callback(null, {
statusCode: redirect_status,
headers: redirect_headers,
body: 'Success!',
}))
.catch(err => {
if(err.code === "NoSuchKey") err.message = "Image not found.";
callback(null, {
statusCode: err.statusCode,
body: err.message,
});
return;
})
} else {
/**
* Resize *.jpg and *.png
*/
// get original key from S3 with Sharp library, resize and put back to S3
S3.getObject({Bucket: BUCKET, Key: originalKey}).promise()
.then(data => sharp(data.Body)
.withoutEnlargement(height==null)
.resize(width, height)
.toFormat(format, {quality: quality})
.toBuffer()
)
.then(buffer => S3.putObject({
Body: buffer,
Bucket: BUCKET,
ContentType: 'image/' + format,
Key: writeKey,
}).promise()
)
.then(() => callback(null, {
statusCode: redirect_status,
headers: redirect_headers,
body: 'Success!',
})
)
.catch(err => {
if(err.code === "NoSuchKey") err.message = "Image not found.";
callback(null, {
statusCode: err.statusCode,
body: err.message,
});
return;
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment