公開日:2020.05.26

Lambdaを試してみました

テクログaws

お久しぶりです。

在宅勤務になり、時間に余裕ができたのでAWSを色々試していました。

今回はLambdaについて紹介したいと思います。

処理の内容はS3のimagesにjpgの画像をアップすると、別のバケットにリサイズされた画像がアップされ、画像のアップロードパスと登録日時がdynamoDBに登録されます。

まず、Lambda上でPillowを使えるようにするために、EC2で下記を実行しました。

sudo yum -y install gcc openssl-devel bzip2-devel libffi-devel
wget https://www.python.org/ftp/python/3.8.1/Python-3.8.1.tgz
tar xzf Python-3.8.1.tgz
cd Python-3.8.1
sudo ./configure --enable-optimizations
sudo make altinstall
pip3.8 install pillow -t .

上記で作成されたPILとPillow.libsとPillow-7.1.2.dist-infoとlambda_function.pyをzipで固めてアップロードします。

次にLambdaのトリガーの設定ですが、S3を選択し、下記内容を入力し、追加をクリックします。

バケット sample
イベントタイプ すべてのオブジェクト作成イベント
プレフィックス-オプション images/
サフィックス-オプション .jpg
トリガーの有効化 チェック

次にdynamoDBで画像管理テーブルとautoincrementがないためidを管理するテーブルを作成します。

テーブルを作成後、idsテーブルにtable_nameがs3_images、idが0を登録します。

・s3_images
id 主キー 数値型
upload_path 文字列型
created_at 文字列型

・ids
table_name 主キー 文字列型
id 数値型

次にS3で下記の二つのバケットを作成します。

sample
sample-resize

最後にlambda_function.pyは下記の内容です。

import boto3
import os
import sys
import uuid
from urllib.parse import unquote_plus
from PIL import Image
import PIL.Image
import datetime

s3_client = boto3.client("s3")
dynamodb = boto3.resource("dynamodb")

def resize_image(image_path, resized_path):
  with Image.open(image_path) as image:
    image.thumbnail(tuple(x / 2 for x in image.size))
    image.save(resized_path)

def get_id(table_name):
  table = dynamodb.Table("ids")
  data = table.update_item(
    Key = {
      "table_name": table_name
    },
    UpdateExpression = "ADD id :id_val",
    ExpressionAttributeValues = {
      ":id_val": 1
    },
    ReturnValues = "UPDATED_NEW"
  )
   
  res = table.get_item(
    Key = {
      "table_name": table_name
    }
  )
  return res["Item"]["id"]

def insert_dynamodb(id, upload_path):
  table= dynamodb.Table("s3_images")
  now = datetime.datetime.now()
  table.put_item(
    Item = {
      "id": id,
      "upload_path": upload_path,
      "created_at": now.strftime("%Y-%m-%d %H:%M:%S")
    }
  )

def lambda_handler(event, context):
  for record in event["Records"]:
    bucket = record["s3"]["bucket"]["name"]
    key = unquote_plus(record["s3"]["object"]["key"])
    tmpkey = key.replace("/", "")
    download_path = "/tmp/{}{}".format(uuid.uuid4(), tmpkey)
    upload_path = "/tmp/resized-{}".format(tmpkey)
    s3_client.download_file(bucket, key, download_path)
    resize_image(download_path, upload_path)
    s3_client.upload_file(upload_path, "{}-resized".format(bucket), key)
     
    id = get_id("s3_images")
    insert_dynamodb(id, upload_path)

これでS3のsampleバケットのimagesにjpgの画像をアップすると、sample-resizeバケットにリサイズされた画像がアップされます。

Lambdaの設定は一部割愛しましたが、以上となります。

この記事を書いた人

JG

入社年2020年

出身地神奈川県

業務内容プログラム

特技または趣味サッカー観戦

JGの記事一覧へ

テクログに関する記事一覧