LoginSignup
5
7

More than 1 year has passed since last update.

【Python】API Gateway + lambda にファイルを post、s3 に保存

Last updated at Posted at 2021-12-06

「Applibot Advent Calendar 2021」 6日目の記事になります!!どうぞよろしくお願いいたします。

1. 概要

ローカルにある csv を lambda に post して、s3にアップロードするまでのメモ。Content-Type の設定をAPI Gateway で行うことを知らず、若干詰まったので記事にしました。

2. 目次

3. aws リソースの用意

3.1. ロールの用意

  • 次のポリシーを持ったロールを作成する
    • AWSLambdaBasicExecutionRole
    • AmazonS3FullAccess

3.2. s3の作成

  • 省略

3.3. lambda関数の作成

  • 3.1 で作成したロールを実行ロールとして指定
  • lambdaにデプロイするコードの作成

    send_csv2s3.py
    import io
    import cgi
    import json
    import boto3
    import base64
    
    BUCKET_NAME='bucket_name'
    DIRECTORY='test_dir/'
    
    s3 = boto3.resource('s3')
    
    def lambda_handler(event, context):
    
        body = base64.b64decode(event['body-json'])
        fp = io.BytesIO(body)
    
        environ = {'REQUEST_METHOD': 'POST'}
        headers = {
            'content-type': event['params']['header']['Content-Type'],
            'content-length': len(body)
        }
    
        bucket = s3.Bucket(BUCKET_NAME)
        fs = cgi.FieldStorage(fp=fp, environ=environ, headers=headers)
        for f in fs.list:
            print("filename=" + f.filename)
            bucket.put_object(Body=f.value, Key=DIRECTORY+f.filename)
    
        return {
            'statusCode': 200,
            'body': json.dumps('Hello World!!')
        }
    
    

3.4. api gateway の作成

  • REST API の構築から作成
  • アクションからメソッドの作成(POST)
    • 3.3 で作成した lambda を関数として作成
  • Content-Type: multipart/form-data を受け取る設定を追加

    • リソース>POST>マッピングテンプレート
      • リクエスト本文のパススルーはテンプレートが定義されていない場合を選択
      • Content-Type に multipart/form-data を入力しチェックマークをクリック
      • テンプレートの生成はプルダウンより メソッドリクエストのパススルー を選択 API Gateway 2021-12-02 15-29-31.png
    • 設定>バイナリメディアタイプ

      • multipart/form-data を追加し保存

      API Gateway 2021-12-02 15-31-12.png

    • IPアドレス制限

      • リソースポリシーに以下を記述
      {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Principal": "*",
                  "Action": "execute-api:Invoke",
                  "Resource": "arn:aws:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
              },
              {
                  "Effect": "Deny",
                  "Principal": "*",
                  "Action": "execute-api:Invoke",
                  "Resource": "arn:aws:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                  "Condition": {
                      "NotIpAddress": {
                          "aws:SourceIp": "xxx.xxx.xxx.xxx/yy"
                      }
                  }
              }
          ]
      }
      
    • デプロイ

      • リソース>アクション>APIのデプロイ

3.5. 疎通の確認

  • csv をポストするコード作成、実行

    send_csv.py
    import os
    import sys
    import json
    import requests
    from glob import glob
    from pathlib import Path
    
    def main():
        csv_dir = "./xxx/xxx"
        csvs = glob(csv_dir + "*.csv")
        a_csv_path = csvs[0]
    
        url = "https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/yyyy" # api gateway>ステージ>urlの呼び出しから確認する
        file_name = os.path.basename(a_csv_path)
        file = {'file': (file_name, open(a_csv_path, 'rb'), 'text/csv')}
    
        res = requests.post(url, files=file)
        print(res)
        print(res.text)
    
    if __name__ == "__main__":
        main()
    
  • 結果の確認

qiita.md — maruichi 2021-12-02 15-34-45.png

完了!!(エラーハンドリング等については追記してください m・・m)

4. 参考

5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7