Last active
November 25, 2021 12:44
-
-
Save kageurufu/68667fcb6d3a08078616 to your computer and use it in GitHub Desktop.
AWS Lambda Thumbnailer
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
var async = require("async"); | |
var AWS = require("aws-sdk"); | |
var gm = require("gm").subClass({imageMagick: true}); | |
var fs = require("fs"); | |
var mktemp = require("mktemp"); | |
var THUMB_KEY_PREFIX = "thumbnails/", | |
THUMB_WIDTH = 150, | |
THUMB_HEIGHT = 150, | |
ALLOWED_FILETYPES = ['png', 'jpg', 'jpeg', 'bmp', 'tiff', 'pdf', 'gif']; | |
var utils = { | |
decodeKey: function(key) { | |
return decodeURIComponent(key).replace(/\+/g, ' '); | |
} | |
}; | |
var s3 = new AWS.S3(); | |
exports.handler = function(event, context) { | |
var bucket = event.Records[0].s3.bucket.name, | |
srcKey = utils.decodeKey(event.Records[0].s3.object.key), | |
dstKey = THUMB_KEY_PREFIX + srcKey.replace(/\.\w+$/, ".png"), | |
fileType = srcKey.match(/\.\w+$/); | |
if(srcKey.indexOf(THUMB_KEY_PREFIX) === 0) { | |
return; | |
} | |
if (fileType === null) { | |
console.error("Invalid filetype found for key: " + srcKey); | |
return; | |
} | |
fileType = fileType[0].substr(1); | |
if (ALLOWED_FILETYPES.indexOf(fileType) === -1) { | |
console.error("Filetype " + fileType + " not valid for thumbnail, exiting"); | |
return; | |
} | |
async.waterfall([ | |
function download(next) { | |
//Download the image from S3 | |
s3.getObject({ | |
Bucket: bucket, | |
Key: srcKey | |
}, next); | |
}, | |
function createThumbnail(response, next) { | |
var temp_file, image; | |
if(fileType === "pdf") { | |
temp_file = mktemp.createFileSync("/tmp/XXXXXXXXXX.pdf") | |
fs.writeFileSync(temp_file, response.Body); | |
image = gm(temp_file + "[0]"); | |
} else if (fileType === 'gif') { | |
temp_file = mktemp.createFileSync("/tmp/XXXXXXXXXX.gif") | |
fs.writeFileSync(temp_file, response.Body); | |
image = gm(temp_file + "[0]"); | |
} else { | |
image = gm(response.Body); | |
} | |
image.size(function(err, size) { | |
/* | |
* scalingFactor should be calculated to fit either the width or the height | |
* within 150x150 optimally, keeping the aspect ratio. Additionally, if the image | |
* is smaller than 150px in both dimensions, keep the original image size and just | |
* convert to png for the thumbnail's display | |
*/ | |
var scalingFactor = Math.min(1, THUMB_WIDTH / size.width, THUMB_HEIGHT / size.height), | |
width = scalingFactor * size.width, | |
height = scalingFactor * size.height; | |
this.resize(width, height) | |
.toBuffer("png", function(err, buffer) { | |
if(temp_file) { | |
fs.unlinkSync(temp_file); | |
} | |
if (err) { | |
next(err); | |
} else { | |
next(null, response.contentType, buffer); | |
} | |
}); | |
}); | |
}, | |
function uploadThumbnail(contentType, data, next) { | |
s3.putObject({ | |
Bucket: bucket, | |
Key: dstKey, | |
Body: data, | |
ContentType: "image/png", | |
ACL: 'public-read', | |
Metadata: { | |
thumbnail: 'TRUE' | |
} | |
}, next); | |
} | |
], | |
function(err) { | |
if (err) { | |
console.error( | |
"Unable to generate thumbnail for '" + bucket + "/" + srcKey + "'" + | |
" due to error: " + err | |
); | |
} else { | |
console.log("Created thumbnail for '" + bucket + "/" + srcKey + "'"); | |
} | |
context.done(); | |
}); | |
}; |
@kageurufu
Thanks for sharing your code. I am facing the problem the deploy Graphicmagick or ImageMagick. Have you compile the binary and upload them with your code as mentioned in https://gist.github.com/bensie/56f51bc33d4a55e2fc9a?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What does it not do that you need? We are still using this in production
https://github.com/DisruptiveLabs/lambda-thumbnailer