S3バケットのファイル内容をLambdaで書き換えて別バケットにアップロードする

# はじめに
本記事では、S3バケットにファイルがアップロードされたときにLambdaを使用でそのファイル内容を修正し、別のバケットにファイルをアップロードする方法について実装します。

# ゴール

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/122f805b-bb16-6891-0601-db0e6954fe3a.png)

S3バケットにファイルをアップロードした際に、LambdaでS3バケットからファイルを取得し、内容を修正したファイルを別のS3バケットにアップロードする

# 前提
下記2つのS3バケットは事前に作成しておきます。
- ファイルダウンロード元のバケット（本記事では変数 `source_bucket`）
- 修正されたファイルのアップロード先となるバケット（本記事では変数 `upload_bucket`）

また、LambdaにはS3へのIAM設定をしておきます。

# 環境
Python 3.12


# Lambda関数の作成

コンソール画面から任意の名前でLambda関数を作成します。
ダウンロード元のS3バケットからファイルをダウンロードしファイルにフルーツの名前を追加した後、別のS3バケットにアップロードします。


```python
import boto3
import os

def lambda_handler(event, context):
    s3 = boto3.client('s3')
    # ダウンロード元のS3バケット
    source_bucket = os.environ['SOURCE_BUCKET']
    file_key = event['Records'][0]['s3']['object']['key']
    # アップロード先のバケット名
    upload_bucket = os.environ['UPLOAD_BUCKET']
    # 追加するフルーツのリスト
    fruits = ['Apple', 'Banana', 'Date', 'Elderberry', 'Fig', 'Grape']
    
    try:
        # ダウンロード元のバケットからファイルを取得
        response = s3.get_object(Bucket=source_bucket, Key=file_key)
        content = response['Body'].read().decode('utf-8')
        
        # ファイルの内容を修正（フルーツ名を追加）
        modified_content = content + "\n\nAdded fruits:\n" + "\n".join(fruits)
        
        # 修正したファイルをS3バケットにアップロード
        s3.put_object(Bucket=upload_bucket, Key=file_key, Body=modified_content)
        print('アップロード完了')
        
        return {
            'statusCode': 200,
            'body':f'ファイル {file_key} のアップロードが成功しました。'
        }
    except Exception as e:
        print(e)
        return {
            'statusCode': 500,
            'body': f'ファイル {file_key} の処理中にエラーが発生しました: {str(e)}'
        }
```


# S3側の準備

ファイルダウンロード元のS3バケット > プロパティを選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/25abca2c-88a3-b068-e639-06cdcaa20e6b.png)


下にスクロールし「イベント通知の作成」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/4a648f76-1cca-0ca7-d4a8-aceb1dac8e13.png)


イベント名を任意の名前で設定し、イベントタイプは`put`チェックをいれておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/7beb52e5-d034-ae8d-2102-66fceb1ebd5a.png)

:::note info

S3のイベント通知の設定において、イベントタイプは `put` の場合はファイルの新規アップロードの場合でもイベントは実行されます。

:::

対象のLambda関数まで選択できたら `変更の保存` を押下して保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/7806ce53-be49-3478-5793-b7cc462394a9.png)


# 動作確認

ファイルの初回アップロードと更新アップロードで動作確認を確認します。

## ファイルの初回アップロード時

下記内容の`sample.txt`ファイルをダウンロード元のバケットにアップロードして、Lambdaが動くかどうか確認します。

```sample.txt
サンプルほげほげ
```

S3にファイルをアップロードすると、CloudWatchにログがはかれてアップロード先のS3バケットにもファイルがアップロードされてる事が確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/32beadc2-e07f-2a57-4cd8-24e709e298ba.png)


```:アップロードされたファイル
サンプルほげほげ

Added fruits:
Apple
Banana
Date
Elderberry
Fig
Grape
```

## ファイルの更新アップロード時

ファイル更新時にLambdaが動き対象のS3バケットにファイルがアップロードされるか確認します。
一度アップロード先のS3バケットのファイルを削除し、再度 sample.txtファイルをダウンロード元のバケットにアップロードしてみると初回アップロードと同様の結果を確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/f803c62b-c650-a153-414c-e2ac5233d456.png)


```:アップロードされたファイル
サンプルほげほげ

Added fruits:
Apple
Banana
Date
Elderberry
Fig
Grape
```