Automated Image Thumbnail Generation
Content Covered
- Solution and simplified architecture diagram
- AWS CDK Script (TypeScript)
- Lambda Function (Python)
Solution
This pipeline demonstrates how to generate thumbnails for images uploaded to an S3 bucket using AWS Lambda and Amazon S3. The system leverages an S3 event notification to trigger a Lambda function that generates thumbnails and stores them back in the S3 bucket. By using AWS Lambda and Amazon S3 together, developers can create a seamless, serverless solution for dynamic thumbnail generation, enhancing the user experience with faster image loading times and optimized storage. This approach exemplifies the power and flexibility of AWS services in building scalable, automated workflows.
Use Case Description
In this scenario, whenever an image is uploaded to a specified S3 bucket, an event notification is sent to AWS Lambda. This event triggers the Lambda function, which contains code specifically written to resize images. Using the AWS SDK, the Lambda function retrieves the newly uploaded image from the S3 bucket.
The function then processes the image, generating a thumbnail with reduced dimensions. This resizing not only saves storage space but also improves load times when the thumbnails are displayed on websites or applications. Once the thumbnail is created, it is uploaded back to a designated folder within the same S3 bucket or to a different bucket, depending on the configuration.
This automated thumbnail generation system is designed to be scalable, capable of handling a high volume of images by leveraging the auto-scaling nature of AWS Lambda. It eliminates the need for manual image processing, thereby reducing operational overhead.
Industry domains
This solution is applicable across various industries, including e-commerce, media, social networking, and content management systems. Any application that involves image uploads and requires thumbnail generation can benefit from this pipeline. Examples include online marketplaces, photo-sharing platforms, and digital asset management systems.
Simplified architecture diagram
The architecture consists of:
- Amazon S3 Bucket: Stores the original images and generated thumbnails.
- AWS Lambda Function: Processes the image uploads and generates thumbnails.
- Amazon S3 Event Notification: Triggers the Lambda function upon image upload.
- IAM Role: Grants necessary permissions to the Lambda function to access S3.
AWS CDK Script (TypeScript)
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as s3n from 'aws-cdk-lib/aws-s3-notifications';
import * as iam from 'aws-cdk-lib/aws-iam';
export class ThumbnailGeneratorStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const bucket = new s3.Bucket(this, 'ImageBucket', {
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
const thumbnailFunction = new lambda.Function(this, 'ThumbnailFunction', {
runtime: lambda.Runtime.PYTHON_3_9,
handler: 'index.handler',
code: lambda.Code.fromAsset('lambda'),
environment: {
BUCKET_NAME: bucket.bucketName,
},
});
bucket.grantReadWrite(thumbnailFunction);
bucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.LambdaDestination(thumbnailFunction));
}
}
Lambda Function (Python)
import os
import boto3
from PIL import Image
from io import BytesIO
s3_client = boto3.client('s3')
def handler(event, context):
bucket_name = os.environ['BUCKET_NAME']
for record in event['Records']:
key = record['s3']['object']['key']
if key.endswith(('jpg', 'jpeg', 'png')):
image_object = s3_client.get_object(Bucket=bucket_name, Key=key)
image_content = image_object['Body'].read()
image = Image.open(BytesIO(image_content))
thumbnail = image.copy()
thumbnail.thumbnail((128, 128))
thumb_io = BytesIO()
thumbnail.save(thumb_io, format=image.format)
thumb_key = f"thumbnails/{key}"
s3_client.put_object(Bucket=bucket_name, Key=thumb_key, Body=thumb_io.getvalue())
return {
'statusCode': 200,
'body': 'Thumbnail generated successfully!'
}