AWSコンソールだけでS3 + Lambdaファイルアップロードトリガーを構築する手順【SAM版との比較付き】

AWS Basic
スポンサーリンク
スポンサーリンク

はじめに

この記事は、SAM版ハンズオン記事の比較版です。

SAM版ではコマンド数本でS3バケット・Lambda・イベント通知設定が完了しましたが、「SAMが裏で何をやっているのか?」「バケット名のグローバルユニーク問題はどう解決する?」「再帰呼び出しの警告って何?」 といった疑問を実際のコンソール操作を通じて体験できるのがこの記事です。

この記事を読むとわかること:

  • S3・Lambda を個別に設定する順序と依存関係
  • SAMの !Sub "${AWS::StackName}-upload-${AWS::AccountId}" が解決していること(バケット名のグローバルユニーク問題)
  • 「再帰呼び出し」警告の意味と、今回は無視してよい理由
  • S3バケット削除時に「先に空にする」が必要な理由

スポンサーリンク

SAM vs コンソール:どれだけ違うか

比較項目SAM(コード)コンソール(手動)
バケット名の一意性確保!Sub "...-${AWS::AccountId}" で自動手動でグローバルユニークな名前を考える
S3イベント通知設定Type: S3 の1行Lambda → トリガーを追加(画面操作)
リソースベースポリシー自動追加トリガー追加時に自動追加(画面の警告を確認する必要あり)
削除バケットを空にしてから sam deleteS3オブジェクト削除 → バケット削除 → Lambda削除 × 個別操作

Amazon検索[本 AWS 開発]

スポンサーリンク

構築するもの

SAM版と全く同じ構成・機能のファイルアップロードトリガー環境を構築します。

ファイルアップロード(コンソール / AWS CLI)
  ↓ S3 ObjectCreated イベント発火
S3 バケット(my-s3-event-upload)
  ↓ Lambda を呼び出し
Lambda(S3EventFunction / Python 3.12)
  ↓ ファイル情報(バケット名・ファイル名・サイズ)をログ出力
CloudWatch Logs

全体の作業順序

① S3 バケット作成
      ↓
② Lambda 関数作成(コード入力)
      ↓
③ S3 トリガーを Lambda に追加(リソースベースポリシーも自動設定)
      ↓
④ ファイルアップロードして動作テスト
⑤ リソースの削除(S3を先に空にする)

順序の理由:
③でS3トリガーを追加する際に「どのバケットを対象にするか」を選択するため、①でバケットを先に作成しておく必要があります。SQSハンズオンのようにARNのコピーが必要な場面はありませんが、バケットが存在しないとトリガー設定画面で選択できません。


① S3 バケット作成

AWSコンソール → S3 → 「バケットを作成」

1-1. バケットの設定

設定項目
バケット名my-s3-event-upload(任意。グローバルで一意な名前)
AWSリージョンアジアパシフィック(東京)ap-northeast-1
オブジェクト所有者ACL 無効(デフォルトのまま)
パブリックアクセスのブロックすべてブロック(デフォルトのまま)
バージョニング無効(デフォルトのまま)
暗号化Amazon S3 マネージドキー(デフォルトのまま)

「バケットを作成」をクリックします。

バケット名のルール(SAMとの違いが出るポイント):

S3のバケット名はAWS全体(全リージョン・全アカウント)でグローバルユニークである必要があります。

  • 小文字・数字・ハイフンのみ使用可(大文字・アンダースコアは使えない)
  • my-s3-event-upload だと他のユーザーがすでに使っている可能性がある

一意にする推奨の方法:

  • my-s3-event-upload-自分のAWSアカウントID(最も確実)
  • my-s3-event-upload-20260222(日付を付ける)

SAMでは !Sub "${AWS::StackName}-upload-${AWS::AccountId}" で自動的にアカウントIDを付加しています。コンソールではこのルールを頭の中で考えて手動入力する必要があります。

控えておく情報:

  • バケット名(例: my-s3-event-upload

② Lambda 関数作成

AWSコンソール → Lambda → 「関数の作成」

2-1. 基本設定

設定項目
作成方法一から作成
関数名S3EventFunction
ランタイムPython 3.12
アーキテクチャx86_64
実行ロール「基本的な Lambda アクセス権限で新しいロールを作成」(デフォルトのまま)

「関数の作成」をクリックします。

実行ロールについて:
今回の Lambda はS3イベントのメタデータ(バケット名・ファイル名・サイズ)を受け取るだけで、S3からファイルの中身を読み取る処理は行いません
そのため、基本実行ロール(CloudWatch Logs への書き込み権限のみ)で動作します。
ファイルの中身を読み取りたい場合は、実行ロールに s3:GetObject 権限を追加する必要があります。

2-2. コードの入力

関数ページ → 「コード」タブ → コードエディタで lambda_function.py を開きます。

既存の内容を全て置き換えて以下を貼り付けます。

import json
import urllib.parse


def lambda_handler(event, context):
    results = []

    for record in event["Records"]:          # 複数ファイル同時アップロードに対応
        bucket = record["s3"]["bucket"]["name"]
        # キー名は URL エンコードされているためデコードが必要(日本語・スペース対応)
        key = urllib.parse.unquote_plus(record["s3"]["object"]["key"])
        size = record["s3"]["object"]["size"]
        event_name = record["eventName"]     # 例: "ObjectCreated:Put"
        event_time = record["eventTime"]     # 例: "2026-02-22T10:00:00.000Z"

        info = {
            "eventName": event_name,
            "bucket": bucket,
            "key": key,
            "sizeBytes": size,
            "eventTime": event_time,
        }

        print(json.dumps(info, ensure_ascii=False))
        results.append(info)

    print(json.dumps({"processedCount": len(results)}, ensure_ascii=False))
    return {"processedCount": len(results)}

「Deploy」ボタンをクリックしてコードを保存します。


③ S3 トリガーを Lambda に追加

Lambdaコンソールからトリガーを追加する方法と、S3コンソールからイベント通知を設定する方法の2つがありますが、ここではLambdaコンソールから行います。

Lambda → S3EventFunction → 「設定」タブ → 「トリガー」→「トリガーを追加」

設定項目
ソースS3
バケット① で作成したバケット(例: my-s3-event-upload
イベントタイプすべてのオブジェクト作成イベント
プレフィックス空欄(全フォルダが対象)
サフィックス空欄(全ファイルタイプが対象)
再帰呼び出し「このトリガーを確認しました」にチェック

「追加」をクリックします。

「再帰呼び出し」の警告とは:

S3バケットへのアップロードをトリガーに同じバケットへ書き込む Lambda を設定すると、無限ループが発生します。例えば「画像をアップロード → Lambdaがリサイズして同じバケットに保存 → それがまたトリガーになる → …」というパターンです。

今回の Lambda はS3への書き込みを行わず、ログを出力するだけなので問題ありません。「このトリガーを確認しました」にチェックして続行してください。

SAMとの差分: SAMの Type: S3 イベントでも同じ構成になっています。SAMは警告なしに設定されますが、同じリスクが存在します。

自動設定されること:
Lambdaのリソースベースポリシーに「S3からの呼び出しを許可するポリシー」が自動追加されます。
S3がLambdaを呼び出すためのIAM設定を手動で行う必要はありません。


④ 動作テスト

4-1. テスト用ファイルの準備

echo テストファイルです > C:\test.txt

4-2. ファイルのアップロード

方法A: S3 コンソールからアップロード

S3 → my-s3-event-upload → 「アップロード」→「ファイルを追加」→ test.txt を選択 → 「アップロード」

方法B: AWS CLI でアップロード

aws s3 cp C:\test.txt s3://my-s3-event-upload/test.txt --region ap-northeast-1

4-3. CloudWatch Logs でログを確認

Lambda → S3EventFunction → 「モニタリング」タブ → 「CloudWatch Logs を表示」→ 最新のログストリームを開きます。

期待するログ出力:

{"eventName": "ObjectCreated:Put", "bucket": "my-s3-event-upload", "key": "test.txt", "sizeBytes": 28, "eventTime": "2026-02-22T10:00:00.000Z"}
{"processedCount": 1}

確認ポイント:

  • "eventName": "ObjectCreated:Put" — S3の Put(アップロード)が検知されている
  • "key": "test.txt" — アップロードしたファイル名が正しく取得されている
  • "sizeBytes" — ファイルサイズが記録されている

4-4. 日本語ファイル名のテスト(任意)

echo 日本語テスト > "C:\テスト.txt"
aws s3 cp "C:\テスト.txt" "s3://my-s3-event-upload/テスト.txt" --region ap-northeast-1

ログで "key": "テスト.txt" と正しくデコードされていることを確認します。


⑤ リソースの削除

課金を止めるために、ハンズオン完了後は必ずリソースを削除してください。

S3バケット削除の重要な注意点:
オブジェクトが残っているバケットは削除できません。
先にバケット内のファイルをすべて削除してからバケットを削除してください。

SAMの sam delete でも同じ理由から「先にバケットを空にする」手順が必要です。この仕様はSAMを使っても変わりません。

1. S3 バケット内のオブジェクトをすべて削除する

方法A: S3 コンソールから

S3 → my-s3-event-upload → ファイルをすべて選択 → 「削除」→ 確認テキストを入力 → 「オブジェクトを削除」

方法B: AWS CLI で一括削除(推奨)

aws s3 rm s3://my-s3-event-upload --recursive --region ap-northeast-1

2. S3 バケットを削除する

S3 → my-s3-event-upload を選択 → 「削除」→ バケット名を入力 → 「バケットを削除」

3. Lambda 関数を削除する

Lambda → 関数 → S3EventFunction を選択 → 「アクション」→「削除」→ 確認テキストを入力 → 「削除」

4. IAM ロールを削除する(任意)

IAM → ロール → S3EventFunction-role-XXXX を選択 → 「削除」→ ロール名を入力 → 「削除」

Lambda を削除してもIAMロールはそのまま残ります。不要なら手動で削除します。

5. CloudWatch Logs のロググループを削除する(任意)

CloudWatch → ロググループ → /aws/lambda/S3EventFunction → 「アクション」→「ロググループの削除」


SAMとの対比まとめ

SAMの記述コンソールでやること
Type: AWS::S3::BucketS3 → バケットを作成
!Sub "${AWS::StackName}-upload-${AWS::AccountId}"手動でグローバルユニークなバケット名を考えて入力
Type: S3 イベント / Events: s3:ObjectCreated:*Lambda → トリガーを追加(S3・全オブジェクト作成イベント)
リソースベースポリシー(自動)トリガー追加時に自動設定(「再帰呼び出し」警告にチェック)
DeletionPolicy: Delete手動でバケットを空にしてからバケット削除
sam deleteS3バケット・Lambda・IAMロール・ロググループを個別に削除

トラブルシューティング

症状原因対処
ファイルをアップロードしてもLambdaが起動しないS3トリガーが設定されていない③ の手順でトリガーを追加する
ログに "key"%XX%XX... と表示されるURLデコードされていないurllib.parse.unquote_plus(key) でデコードしているか確認
バケット削除がエラーになるバケット内にオブジェクトが残っているaws s3 rm s3://バケット名 --recursive で先に空にする
Lambda が 500 エラーコードの構文エラーなどCloudWatch Logs でエラー内容を確認
トリガー追加時に「再帰呼び出し」の警告が出る同バケットへの書き込みトリガーへの注意今回のLambdaはS3に書き込まないためチェックを入れて続行

まとめ

コンソール操作で確認できたこと

SAMの記述コンソール操作で理解できたこと
!Sub "...-${AWS::AccountId}"バケット名のグローバルユニーク問題を手動で解決する必要がある
Type: S3 イベント(自動)トリガー追加画面で「再帰呼び出し警告」の意味を確認できる
DeletionPolicy: DeleteS3は「先に空にしてから削除」が必須ルール(SAMでも同じ)

どちらを使うべきか

シーン推奨
本番環境・チーム開発SAM(バケット名の管理・再現性・速度)
AWSを初めて学ぶコンソール(各設定の意味を理解する)
構築済みリソースの確認・デバッグコンソール(S3のオブジェクト確認・イベント通知設定の目視)
同じ構成を繰り返しデプロイSAM(ミスゼロ・自動化)

関連記事

  • SAM版ハンズオン — コマンド数本でS3 + Lambdaトリガー環境を構築
AWSハンズオン - S3へのファイルアップロードをトリガーにLambdaを自動起動しよう【SAM版 / Windows対応】
はじめに「S3にファイルが上がったら自動で処理したい」というのは、AWSを使う現場でよく出てくる要件です。画像のリサイズ、CSVの集計、ログファイルの解析など、ファイルアップロードを起点にした自動処理はサーバーレス構成の代表的なユースケース...

Amazon検索[本 AWS 開発]

コメント