背景
S3へのファイルアップロードをトリガーにLambdaを起動する構成をAWS SAMで構築しました。日本語ファイル名やフォルダ付きキーを扱う際に必要な処理を整理します。
1. Type: S3イベントの最小構成
Resources:
UploadBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${AWS::StackName}-upload-${AWS::AccountId}"
DeletionPolicy: Delete
S3EventFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src/
Handler: app.lambda_handler
Events:
S3Event:
Type: S3
Properties:
Bucket: !Ref UploadBucket
Events: s3:ObjectCreated:*
Type: S3の1行で、S3側のイベント通知設定と、Lambda側の「S3からの呼び出しを許可するリソースベースポリシー」の両方が自動作成されます。
2. バケット名は!Sub "...-${AWS::AccountId}"でグローバルユニーク化
S3バケット名はAWS全体(全リージョン・全アカウント)で一意である必要があります。
BucketName: !Sub "${AWS::StackName}-upload-${AWS::AccountId}"
スタック名だけでは他アカウントと衝突する可能性があるため、アカウントIDを含めるのが確実な方法です。一度使われたバケット名は削除後もしばらく再利用できないことがあるため、この命名規則は覚えておいて損はありません。
3. urllib.parse.unquote_plusが必須な理由
import urllib.parse
def lambda_handler(event, context):
for record in event["Records"]:
key = urllib.parse.unquote_plus(record["s3"]["object"]["key"])
S3のキー名に日本語やスペース、特殊文字が含まれると、Lambdaに渡されるeventの中ではURLエンコードされた状態になります。
| アップロードしたファイル名 | デコード前 | デコード後 |
|---|---|---|
テスト.txt |
%E3%83%86%E3%82%B9%E3%83%88.txt |
テスト.txt |
my file.txt |
my+file.txt |
my file.txt |
unquote_plusを使わないと、ログや後続処理で%E3%83%86...のような文字列がそのまま流れてしまいます。unquoteではなくunquote_plusを使うのは、スペースが+に変換されるケース(my+file.txt)にも対応するためです。
4. event["Records"]は複数件になり得る
for record in event["Records"]:
bucket = record["s3"]["bucket"]["name"]
key = urllib.parse.unquote_plus(record["s3"]["object"]["key"])
通常は1件ですが、複数ファイルの同時アップロード(マルチパートアップロードの完了通知など)ではRecordsが複数件になる場合があります。forループを前提にした実装にしておくのが安全です。
5. DeletionPolicy: Deleteでも空にしないと削除できない
UploadBucket:
Type: AWS::S3::Bucket
DeletionPolicy: Delete
DeletionPolicy: Deleteを指定していても、オブジェクトが1件でも残っているバケットはCloudFormationから削除できません。
aws s3 rm s3://バケット名 --recursive --region ap-northeast-1 # 先に空にする
sam delete --stack-name スタック名 --region ap-northeast-1
これを忘れるとsam deleteが以下のエラーで失敗します。
Error: Failed to delete the stack: ...
The following resource(s) failed to delete: [UploadBucket]
まとめ
unquote_plusによるURLデコードと、削除前のバケット空化、この2点がS3イベントLambdaの実装・運用で押さえておくべきポイントでした。フォルダ付きキーや複数ファイル同時アップロードの検証手順は元記事にまとめています。