Resize and Optimize Images Uploaded to S3 Using AWS Lambda and Kraken.io

Andi Ashari
3 min readNov 4, 2018

--

Instead of burdening your application just to resize and optimize the image then save it in S3, it’s better using AWS Lambda which is triggered from S3 to resize and optimize the image, thus making your application only upload it to S3 and let the AWS Lambda resize and optimize every image uploaded.

In this article, we will use Kraken.io to resize and optimize our images, you can freely use 3rd party or using NodeJS image compression library like sharp, imagemin, or anything else.

Step 01: Flow Process

Process Flow of Resizing and Optimizing using Lambda and Kraken
  • Application upload image to S3 bucket
  • S3 triggered lambda function
  • Lambda function sends the image to Kraken.io through public URL
  • Kraken.io will resize and optimize our image based on parameter we send
  • Kraken.io send back the optimized image to S3 bucked based on parameter we send
  • Done

Step 02: Create Lambda function

Create lambda function, let say we named it ‘kraken-image-optimizer’ then add trigger from S3 with below information:

  • Bucket: {{your bucket name}}
  • Event Type: Object Created (All)
  • Prefix: {{your specific path}}
  • Suffix: {{your specific suffix}}

Then click enable trigger and click add.

Step 03: Code Lambda function

  • Lambda get an event from S3 ObjectCreated (All) in below section:
exports.handler = (event, context, callback) => {
let records = event.Records;
for (let i = 0; i < records.length; i++) {
processFile(records[i]);
}
};
  • Then we iterate all files triggered into processFile function, inside processFile function, we validate if the file name starts with rl-(we add the prefix rl-to every processed image from Kraken.io) then we skip that file, or if the file was not an image we also skip that file.
function processFile(file) {

let filePath = file.s3.object.key;
let fileBucket = file.s3.bucket.name;

let fileName = filePath.split('/');
fileName = fileName[fileName.length-1];

if(fileName.indexOf('rl-')===0){
return;
}

if(!(filePath.indexOf('.jpg')>0 || filePath.indexOf('.png')>0)){
return;
}
//=> ...}
  • The next step, we send the image public URL into Kraken.io using our custom params, and save it into our S3 bucket with prefix rl-:
function processFile(file) {

//=> ...
var Kraken = require("kraken");var kraken = new Kraken({
"api_key": "{{your kraken.io API key}}",
"api_secret": "{{your kraken.io Secret key}}"
});
var params = {
url: "https://s3-ap-southeast-1.amazonaws.com/{{bucket-name}}/" + filePath,
wait: true,
lossy: false,
resize: {
"width": 800,
"height": 600,
"strategy": "auto"
},
"s3_store": {
"key": "{{bucket-key}}",
"secret": "{{bucket-secret}}",
"bucket": "{{bucket-name}}",
"path": filePath.replace(fileName,'rl-'+fileName),
"region": "{{bucket-region}}"
}
};
kraken.url(params, function(data, status) {
if (status && status.success) {

} else {
console.log("Fail. Error message: %s", JSON.stringify(data));
}
});
}

So here is the full code of my Lambda function:

var https = require('https');
var querystring = require('querystring');
var kraken = require("kraken");
exports.handler = (event, context, callback) => {
let records = event.Records;
for (let i = 0; i < records.length; i++) {
processFile(records[i]);
}
};function processFile(file) {

let filePath = file.s3.object.key;
let fileBucket = file.s3.bucket.name;

let fileName = filePath.split('/');
fileName = fileName[fileName.length-1];

if(fileName.indexOf('rl-')===0){
return;
}

if(!(filePath.indexOf('.jpg')>0 || filePath.indexOf('.png')>0)){
return;
}
var Kraken = require("kraken");var kraken = new Kraken({
"api_key": "{{your kraken.io API key}}",
"api_secret": "{{your kraken.io Secret key}}"
});
var params = {
url: "https://s3-ap-southeast-1.amazonaws.com/{{bucket-name}}/" + filePath,
wait: true,
lossy: false,
resize: {
"width": 800,
"height": 600,
"strategy": "auto"
},
"s3_store": {
"key": "{{bucket-key}}",
"secret": "{{bucket-secret}}",
"bucket": "{{bucket-name}}",
"path": filePath.replace(fileName,'rl-'+fileName),
"region": "{{bucket-region}}"
}
};
kraken.url(params, function(data, status) {
if (status && status.success) {

} else {
console.log("Fail. Error message: %s", JSON.stringify(data));
}
});
}

Step 03: Test upload image into your bucket

The last step was to test your function, test uploading high-resolution image above 1024 pixels then see the result, according to the code, the result will resize every image above 800 px into 800px and max high was 600px.

--

--

Andi Ashari

Tech Wanderer, Passionate about Innovation and Deeply Expertised in Technology. Actively Redefining the Digital Landscape Through Cutting-Edge Solutions.