Resizing S3 Images With AWS Lambda Trigger

Sahan Amarsha
6 min readJul 16, 2022

--

Let’s create an AWS Lambda function to resize images using npm Sharp Image Library

👋 Hi Guys! After many trial and error attempts, I was finally able to create an AWS Lambda Trigger to resize images on the fly. So, here I am, writing a guide so that you can save your time while implementing similar functionality.

We will use the Sharp Image Library. Sharp is a high-speed npm library for converting large images into smaller web-friendly images. As I have noticed, Sharp is extremely fast than other image libraries.

Why Did I Use AWS Lambda Trigger?

I thought of having a Lambda Trigger that can resize images on the fly. I can use that to save up some space in my S3 bucket.

I could implement that in two ways. One way is to tweak the client-side code, to resize the image before uploading it to S3. My main concern was about the performance. It’s not reliable as well. 💭

Next, I turned into implementing a Lambda Trigger that will get invoked when we upload an image to the S3 bucket. After resizing, the lambda function will replace the image. So, I continued that approach, and I’ll explain the steps that I followed.

Let’s dive in. 🤿

Prerequisites

You will certainly need an AWS account to complete this tutorial. We can complete this app using AWS free-tier, but you need to enter your credit card to create a new account.

To avoid any disturbances, make sure you have the following prerequisites installed.

Step 1: Initialize Amplify Project

Alright then, first we need to initialize an Amplify Project. To make this tutorial more fun, I created this React App which can display uploaded S3 images. You can clone that project to get started.

⭐ Github Starter React App Project: https://github.com/SahanAmarsha/image-resizer-frontend

git clone https://github.com/SahanAmarsha/image-resizer-frontend

Next, we need to move into our project directory and install the dependencies.

cd image-resizer-frontend
npm install

Now, let’s initialize a new Amplify Project.

amplify init

We will get prompted for a few configurations. Just accept the defaults, and we are good to go. (If you did not install Amplify CLI yet, you can refer to this video walkthrough)

Initializing an Amplify Backend

Step 2: Create a Lambda Trigger

Now that we have initialized an Amplify Project. Next, we need to provision the S3 Storage resource.

amplify add storage

To use Amplify Storage Service, we also need to enable Auth Service.

First provisioning Auth Resource

Next, Amplify CLI will walk us through the options to name the S3 bucket, to enable user permissions, and the last option is important for this tutorial. Amplify CLI prompts to associate a Lambda trigger with our S3 bucket, Choose yes(y).

Create Amplify S3 bucket Lambda trigger

Now we have already created Auth, Storage, and Function services locally. Let’s push those resources into the cloud.

amplify push --y

Step 3: Implement the Lambda Function

We can go to AWS Amplify Console by running amplify console in our project directory. Just remember to choose AWS Console.

View Amplify project in AWS console

To view the Amplify project, you need to log into your AWS account first. Let’s navigate to the Lambda Function console. In your Amplify project, go to Functions and choose View in Lambda.

Choosing View in Lambda

Then you will get navigated to our Lambda Function console. It looks something like this.

Lambda Function Console

Before updating this Lambda function, we need to talk.

Sharp Library Cross Platform Issue

As I’ve said earlier, Sharp is a really fast image resizing library. This library will save a lot of cost by limiting the execution time of our Lambda function.

If we try to use Sharp with lambda, the library will not work in the first place. Here is the reason.

The architecture and platform of Node.js used for npm install must be the same as the architecture and platform of Node.js used at runtime.

🤓 Let me explain this to you.

❌ Let’s say, I installed sharp in my Windows OS using npm install sharp and implemented the function locally under amplify/backend/ function/your_function_name/src/index.js. However, binaries inside the node_modules folder will only suit Windows OS. Lambda function won’t work because it executes on a Linux x64 instance.

🤔 Now, how do we resolve this?

Luckily I had VirtualBox installed. So, I created a Linux virtual instance, installed the dependencies, and pushed that function into the AWS console. Don’t worry you don’t need to put up a Linux virtual instance to complete this tutorial 😅.

That’s why I decided to make this tutorial so that you don’t need to go through all that.

You can clone my lambda image resizer repo.

⭐ Github Lambda Image Resizing Function (with pre-installed Sharp library): https://github.com/SahanAmarsha/image-resizer-lambda

There you will find an already bundled zip file called image_resizer_test.zip. On index.js file, I have already included the code to resize the S3 image.

SahanAmarsha/lambda-image-resizer/index.js

Let’s walk through the code.

  • s3.getObject({ Bucket: bucket, Key: key}).promise() — S3 event contains bucket and key values. By using these two values, we can get the S3 image object.
  • image.resize({ width: 900 }).withMetadata().toBuffer() — The S3 image object will get resized, without changing the rotation of the image.
  • s3.putObject({ Bucket: bucket, Key: key, Body: resizedImage }) — Since we are using the same bucket and key values, the original S3 object will get replaced.
  • if(metadata.width > 900) — This will avoid recursion. Since we are using the same S3 bucket to upload the resized image. The Lambda function will get triggered one more time.

However, do not unzip image_resizer_test.zip if you are using any OS other than Linux x64. We can use a utility tool like WinRAR, to edit the implementations at index.js without unzipping the files.

Update index.js without unzipping the files

Now, all we need to do is to upload the zip file into the Lambda function. Go back to the Lambda console. Select upload from and choose .zip file.

Upload .zip file into Lambda

Step 4: Testing the Lambda Function

We have already implemented our Lambda function. Now, let’s test this out. We can go back to our Amplify project. Go to File Storage> View in S3.

Create a new public folder inside the S3 bucket. Choose upload from and select the image you want to upload. Do make sure to grant public access. Otherwise, we won’t be able to pull the image from our React application.

Uploading an image with public-access

Now we can see our Lambda function in action.

Image file size before & after Lambda function

Let’s spin up our React application to view these images. Before npm start, we need to configure our Amplify resources inside index.js. So make sure to add the following at top of the file.

import {Amplify, Auth} from "aws-amplify";
import awsconfig from './aws-exports';
import '@aws-amplify/ui-react/styles.css';

Amplify.configure(awsconfig);
Auth.configure(awsconfig);

Now, if we re-run our application, we should be able to view our images.

React frontend application (Image Credits: https://unsplash.com)

That’s it for this tutorial. You have successfully implemented an AWS Lambda function to resize images on the fly. 🎉

Conclusion

I hope you found this tutorial helpful.

Feel free to ask any questions, in the comments section below.
Happy Coding! 😃

🖥️ Resources

--

--

Sahan Amarsha
Sahan Amarsha

Written by Sahan Amarsha

Full Stack Developer | AWS Community Builder | https://www.iamsahan.me

Responses (1)