「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.pyimport 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>マッピングテンプレート
-
設定>バイナリメディアタイプ
-
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.pyimport 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()
-
結果の確認
完了!!(エラーハンドリング等については追記してください m・・m)