2020.05.26
STAFF BLOG
スタッフブログ
TECHNICAL
テクログ

お久しぶりです。
在宅勤務になり、時間に余裕ができたので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の設定は一部割愛しましたが、以上となります。