Real-Time Amazon S3 Trigger for AWS Lambda Thumbnail Creation Demo

AWS Lambda Thumbnail Creation Demo We Will Use Serverless Framework Along With

  • S3 Events
  • Function timeouts and memory
  • IAM Permissions
  • Plugins to deploy python dependencies
  • Custom Variables
  • Environment Variables

Serverless Framework

Imagine a world where you can focus solely on your code without ever worrying about server management. That’s the promise of the serverless framework—a revolutionary approach to building and deploying applications where developers can unleash their creativity without the constraints of traditional infrastructure concerns. With serverless, your code runs in response to events, automatically scaling to meet demand, while you pay only for the resources you use. It’s the future of application development, where innovation knows no bounds.

https://www.serverless.com

Serverless Framework aims to ease the pain of creating, deploying, managing and debugging lambda functions. It has CloudFormation support so your entire stack can be deployed using this framework

Installing Serverless

Install dependencies (node & AWS CLI)

Install Serverless Framework ( sudo npm install -g serverless )

Setting up AWS for the `serverless-admin` user:

Create IAM user with Access Keys

Download credentials on your machine

Setup Serverless to use these credentials ( serverless config credentials --provider aws --key <access key> --secret <secret access key> profile serverless serverless-admin )

Want to learn a Beginner’s Guide to Serverless Computing?

Setup AWS Lambda Thumbnail Creation Generator Code

serverless.yml

service: python-s3-thumbnail

frameworkVersion: '3'

provider:
  name: aws
  runtime: python3.10
  region: us-east-1
  profile: server-admin
  stage: "dev"
  timeout: 10
  memorySize: 128
  environment:
    THUMBNAIL_SIZE: "128"
    REGION_NAME: ${self:provider.region}
 
  iam:
    role:
      statements:
        - Effect: 'Allow'
          Resource: 'arn:aws:s3:::rtvishnu-thumbnails/*'
          Action: 's3:*'
  
custom:
  bucket: rtvishnu-thumbnails
  pythonRequirements:
   # pythonBin: /opt/python3.8/bin/python
    dockerizePip: true

functions:
  s3_thumbnail_generator:
    handler: handler.s3_thumbnail_generator
    events:
      - s3:
          bucket: ${self:custom.bucket}
          event: s3:ObjectCreated:*
          rules:
            - suffix: .png

#MUST first run: serverless plugin install -n serverless-python-requirements
plugins:
  - serverless-python-requirements

handler.py


from datetime import datetime
import boto3
import PIL
from io import BytesIO
from PIL import Image, ImageOps
import os
import uuid
import json

s3 = boto3.client('s3')
size = int(os.environ['THUMBNAIL_SIZE'])

def s3_thumbnail_generator(event, context):
    # parse event
    print("EVENT:::", event)
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = event['Records'][0]['s3']['object']['key']
    img_size = event['Records'][0]['s3']['object']['size']

    # only create a thumbnail on non thumbnail pictures
    if (not key.endswith("_thumbnail.png")):

        # get the image
        image = get_s3_image(bucket, key)

        # resize the image
        thumbnail = image_to_thumbnail(image)

        # get the new filename
        thumbnail_key = new_filename(key)
        # upload the file
        url = upload_to_s3(bucket, thumbnail_key, thumbnail, img_size)
        return url

def get_s3_image(bucket, key):
    response = s3.get_object(Bucket=bucket, Key=key)
    imagecontent = response['Body'].read()

    file = BytesIO(imagecontent)
    img = Image.open(file)
    return img


def image_to_thumbnail(image):
    return ImageOps.fit(image, (size, size), PIL.Image.Resampling.LANCZOS)


def new_filename(key):
    key_split = key.rsplit('.', 1)
    return key_split[0] + "_thumbnail.png"

def upload_to_s3(bucket, key, image, img_size):
    # We're saving the image into a BytesIO object to avoid writing to disk
    out_thumbnail = BytesIO()  # old way- no longer supported fp.StringIO()

    # You MUST specify the file type because there is no file name to discern
    # it from
    image.save(out_thumbnail, 'PNG')
    out_thumbnail.seek(0)

    response = s3.put_object(
        ACL='public-read',
        Body=out_thumbnail,
        Bucket=bucket,
        ContentType='image/png',
        Key=key
    )
    print(response)

    url = '{}/{}/{}'.format(s3.meta.endpoint_url, bucket, key)

    return url

We imported PIL and in lambda we need to add a layer dependency. I have used a github repository ( https://github.com/keithrozario/Klayers ) to get the list of ARNs. Get the ARN with respect to the python package version and add layer to lambda function by specifying the ARN

Now deploy the code ( sls deploy )

Check AWS S3 and AWS lambda console, Thumbnail services will be deployed automatically

Buckets are created

Lambda Function Created

Now to test the thumbnail generator service, upload image of type png in rtvishnu-thumbnails bucket and it should trigger lambda function to create thumbnail image (reduce the size of original)

The thumbnail image is resized to a smaller size.

1 thought on “Real-Time Amazon S3 Trigger for AWS Lambda Thumbnail Creation Demo”

  1. Pingback: Enabling Email Subscriptions With AWS SNS - wordwyzz

Leave a Comment

Your email address will not be published. Required fields are marked *