Resizing S3 Images With AWS Lambda Trigger
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.
- Node.js v10.x or later
- npm v5.x or later
- Amplify CLI (v9.1.0 what I’m using in the tutorial)
- Git
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)
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.
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).
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
.
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
.
Then you will get navigated to our Lambda Function console. It looks something like this.
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.
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.
index.js
without unzipping the filesNow, 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
.
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.
Now we can see our Lambda function in action.
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.
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
- Image Resizing Frontend Project — https://github.com/SahanAmarsha/image-resizer-frontend
- Image Resizing Lambda Function — https://github.com/SahanAmarsha/image-resizer-lambda