Created
March 18, 2018 17:17
-
-
Save AntoniusGolly/eee090526e4140ca34f0aa4ea5d571cc to your computer and use it in GitHub Desktop.
Sample Node.js script for resizing images with the Sharp library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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