Skip to content

Commit 95fab6d

Browse files
committed
New pattern - S3 Lambda resizing image (python)
1 parent be903e3 commit 95fab6d

File tree

8 files changed

+241
-0
lines changed

8 files changed

+241
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# AWS Amazon S3 to AWS Lambda - Create a Lambda function that resizes images uploaded to S3
2+
3+
The SAM template deploys a Lambda function, an S3 bucket and the IAM resources required to run the application. A Lambda function consumes <code>ObjectCreated</code> events from an Amazon S3 bucket. The Lambda code checks the uploaded file is an image and creates a thumbnail version of the image in the same bucket.
4+
5+
Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.
6+
7+
## Requirements
8+
9+
* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
10+
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
11+
* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
12+
* [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) (AWS SAM) installed
13+
14+
## Deployment Instructions
15+
16+
1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
17+
```
18+
git clone https://github.com/aws-samples/serverless-patterns
19+
```
20+
1. Change directory to the pattern directory:
21+
```
22+
cd s3-lambda
23+
```
24+
1. From the command line, use AWS SAM to build and deploy the AWS resources for the pattern as specified in the template.yml file:
25+
```
26+
sam build
27+
sam deploy --guided
28+
```
29+
1. During the prompts:
30+
* Enter a stack name
31+
* Enter the desired AWS Region
32+
* Allow SAM CLI to create IAM roles with the required permissions.
33+
34+
Once you have run `sam deploy --guided` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy` in future to use these defaults.
35+
36+
1. Note the outputs from the SAM deployment process. These contain the resource names and/or ARNs which are used for testing.
37+
38+
## How it works
39+
40+
* Use the AWS CLI upload an image to S3
41+
* If the object is a .jpg or a .png, the code creates a thumbnail and saves it to the target bucket.
42+
* The code assumes that the destination bucket exists and its name is a concatenation of the source bucket name followed by the string -resized
43+
44+
==============================================
45+
46+
## Testing
47+
48+
Run the following S3 CLI command to upload an image to the S3 bucket. Note, you must edit the {SourceBucketName} placeholder with the name of the S3 Bucket. This is provided in the stack outputs.
49+
50+
```bash
51+
aws s3 cp './events/example.jpg' s3://{SourceBucketName}
52+
```
53+
54+
Run the following command to check that a new version of the image has been created in the destination bucket.
55+
56+
```bash
57+
aws s3 ls s3://{DestinationBucketName}
58+
```
59+
60+
## Cleanup
61+
62+
1. Delete the stack
63+
```bash
64+
aws cloudformation delete-stack --stack-name STACK_NAME
65+
```
66+
1. Confirm the stack has been deleted
67+
```bash
68+
aws cloudformation list-stacks --query "StackSummaries[?contains(StackName,'STACK_NAME')].StackStatus"
69+
```
70+
----
71+
Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
72+
73+
SPDX-License-Identifier: MIT-0
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"Records": [
3+
{
4+
"eventVersion": "2.1",
5+
"eventSource": "aws:s3",
6+
"awsRegion": "us-east-1",
7+
"eventTime": "2024-07-03T19:37:27.192Z",
8+
"eventName": "ObjectCreated:Put",
9+
"userIdentity": {
10+
"principalId": "AWS:AIDAINPONIXQXHT3IKHL2"
11+
},
12+
"requestParameters": {
13+
"sourceIPAddress": "205.255.255.255"
14+
},
15+
"responseElements": {
16+
"x-amz-request-id": "D82B88E5F771F645",
17+
"x-amz-id-2": "vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo="
18+
},
19+
"s3": {
20+
"s3SchemaVersion": "1.0",
21+
"configurationId": "828aa6fc-f7b5-4305-8584-487c791949c1",
22+
"bucket": {
23+
"name": "<provide-source-bucket-name-here>",
24+
"ownerIdentity": {
25+
"principalId": "A3I5XTEXAMAI3E"
26+
},
27+
"arn": "arn:aws:s3:::lambda-artifacts-deafc19498e3f2df"
28+
},
29+
"object": {
30+
"key": "<provide-source-object-key-here>",
31+
"size": 1305107,
32+
"eTag": "b21b84d653bb07b05b1e6b33684dc11b",
33+
"sequencer": "0C0F6F405D6ED209E1"
34+
}
35+
}
36+
}
37+
]
38+
}
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"title": "AWS Amazon S3 to AWS Lambda Image Resizing",
3+
"description": "Create a Lambda function that resizes images uploaded to S3.",
4+
"language": "Python",
5+
"level": "200",
6+
"framework": "SAM",
7+
"introBox": {
8+
"headline": "How it works",
9+
"text": [
10+
"A Lambda function consumes events from an Amazon S3 bucket. The Lambda code checks the uploaded file is an image and creates a thumbnail version of the image in the destination bucket.",
11+
"This pattern deploys a Lambda function and two S3 buckets."
12+
]
13+
},
14+
"gitHub": {
15+
"template": {
16+
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/s3-lambda-resizing-python",
17+
"templateURL": "serverless-patterns/s3-lambda-resizing-python",
18+
"projectFolder": "s3-lambda-resizing-python",
19+
"templateFile": "template.yaml"
20+
}
21+
},
22+
"resources": {
23+
"bullets": [
24+
{
25+
"text": "Process S3 events with Lambda",
26+
"link": "https://docs.aws.amazon.com/lambda/latest/dg/with-s3.html"
27+
}
28+
]
29+
},
30+
"deploy": {
31+
"text": [
32+
"sam deploy --guided"
33+
]
34+
},
35+
"testing": {
36+
"text": [
37+
"See the GitHub repo for detailed testing instructions."
38+
]
39+
},
40+
"cleanup": {
41+
"text": [
42+
"Delete the application: <code>sam delete</code>."
43+
]
44+
}
45+
}

s3-lambda-resizing-python/hello_world/__init__.py

Whitespace-only changes.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import boto3
2+
import uuid
3+
from urllib.parse import unquote_plus
4+
from PIL import Image
5+
6+
s3_client = boto3.client('s3')
7+
8+
def resize_image(image_path, resized_path):
9+
with Image.open(image_path) as image:
10+
image.thumbnail(tuple(x / 2 for x in image.size))
11+
image.save(resized_path)
12+
13+
def lambda_handler(event, context):
14+
for record in event['Records']:
15+
bucket = record['s3']['bucket']['name']
16+
key = unquote_plus(record['s3']['object']['key'])
17+
tmpkey = key.replace('/', '')
18+
download_path = '/tmp/{}{}'.format(uuid.uuid4(), tmpkey)
19+
upload_path = '/tmp/resized-{}'.format(tmpkey)
20+
s3_client.download_file(bucket, key, download_path)
21+
resize_image(download_path, upload_path)
22+
s3_client.upload_file(upload_path, '{}-resized'.format(bucket), 'resized-{}'.format(key))
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pillow
2+
boto3
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
AWSTemplateFormatVersion: '2010-09-09'
2+
Transform: AWS::Serverless-2016-10-31
3+
Description: Image resizing service (tag:s3-lambda)
4+
5+
Parameters:
6+
SourceBucketName:
7+
Type: String
8+
DestinationBucketName:
9+
Type: String
10+
11+
Resources:
12+
## S3 bucket
13+
SourceBucket:
14+
Type: AWS::S3::Bucket
15+
Properties:
16+
BucketName: !Ref SourceBucketName
17+
DestinationBucket:
18+
Type: AWS::S3::Bucket
19+
Properties:
20+
BucketName: !Ref DestinationBucketName
21+
22+
## Lambda function
23+
ResizerFunction:
24+
Type: AWS::Serverless::Function
25+
Properties:
26+
CodeUri: src/
27+
Handler: app.lambda_handler
28+
Runtime: python3.12
29+
MemorySize: 2048
30+
Layers:
31+
- !Sub 'arn:aws:lambda:${AWS::Region}:175033217214:layer:graphicsmagick:2'
32+
Policies:
33+
- S3ReadPolicy:
34+
BucketName: !Ref SourceBucketName
35+
- S3CrudPolicy:
36+
BucketName: !Ref DestinationBucketName
37+
Environment:
38+
Variables:
39+
DESTINATION_BUCKETNAME: !Ref DestinationBucketName
40+
Events:
41+
FileUpload:
42+
Type: S3
43+
Properties:
44+
Bucket: !Ref SourceBucket
45+
Events: s3:ObjectCreated:*
46+
Filter:
47+
S3Key:
48+
Rules:
49+
- Name: suffix
50+
Value: '.jpg'
51+
Outputs:
52+
SourceBucketName:
53+
Value: !Ref SourceBucketName
54+
Description: S3 Bucket for object storage
55+
DestinationBucketName:
56+
Value: !Ref DestinationBucketName
57+
Description: S3 destination Bucket for object storage
58+
FunctionArn:
59+
Value: !Ref ResizerFunction
60+
Description: ResizerFunction function Arn

0 commit comments

Comments
 (0)