Overview
In this note, we will explore how to use AWS Lambda to compress images stored in Amazon S3 and log the details of the operation into DynamoDB. This is a common use case for optimizing storage and improving performance when serving images.
Prerequisites
- S3 Bucket: You need two S3 buckets - one for the source images (e.g.,
source-bucket) and another for the compressed images (e.g.,destination-bucket). - DynamoDB Table: Create a DynamoDB table (e.g.,
ImageLogs) with a Partition Key namedImageID(String). - Lambda Layer: Since the standard Python environment in Lambda does not include image processing libraries, you will need to add the Pillow (PIL) library through a Lambda Layer.
AWS Lambda Function (Python)
Here is an example code using boto3 and Pillow:
import boto3
import os
import uuid
from datetime import datetime
from PIL import Image
import io
s3 = boto3.client('s3')
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('ImageLogs')
def lambda_handler(event, context):
# 1. Get information about the uploaded image from the event
bucket_name = event['Records'][0]['s3']['bucket']['name']
key = event['Records'][0]['s3']['object']['key']
# Choose the target bucket (can be the same or different)
target_bucket = "destination-bucket"
download_path = '/tmp/{}'.format(key)
upload_path = 'compressed-{}'.format(key)
# 2. Download image from S3 to temporary storage (/tmp)
s3.download_file(bucket_name, key, download_path)
# 3. Process compression using Pillow
with Image.open(download_path) as img:
# Example compression by reducing quality to 60%
img.save(upload_path, "JPEG", optimize=True, quality=60)
# 4. Upload again into S3
s3.upload_file(upload_path, target_bucket, key)
# 5. Log into DynamoDB
image_id = str(uuid.uuid4())
table.put_item(
Item={
'ImageID': image_id,
'OriginalName': key,
'SourceBucket': bucket_name,
'ProcessedAt': datetime.now().isoformat(),
'Status': 'Success'
}
)
return {
'statusCode': 200,
'body': f'Image {key} successfully compressed and logged.'
}Configuring Permissions (IAM Role)
Lambda function needs “keys” to access other services. Make sure the Lambda Execution Role has the following policies:
- AmazonS3FullAccess (or specific to your buckets): To read and upload images.
- AmazonDynamoDBFullAccess: To write logs to the table.
- AWSLambdaBasicExecutionRole: To allow Lambda to write logs to CloudWatch (for debugging).
Prepare the Lambda Trigger
In the AWS Lambda console:
- Click on “Add Trigger”.
- Select “S3”.
- Choose your source bucket.
- Select “Event type: All object create events”.
- (Optional) Check “Recursive invocation” if you want to trigger on all subfolders (be cautious: if you upload the compressed results to the same bucket, this can trigger an infinite loop. It’s better to use a different bucket or filter by prefix/folder).
Useful Tips
- Memory: Image compression can be memory-intensive. Set the Lambda memory to at least 512MB or more if you are processing large images.
- Timeout: The image processing might take several seconds, so increase the default Lambda timeout from 3 seconds to around 1 minute to avoid timeouts during processing.