いろいろなやり方があるようで、右往左往してしまったので、その経緯を備忘録的に残します。
結論として、
- API gatewayでマッピングテンプレートを設定する
- API gatewayでバイナリメディアタイプを設定する
- lambdaロールにS3へのアクセス権限を付与する
がポイントのようです。
lambda関数の作成
pythonで作成します。
-
参考記事のままですが以下のコードを使用しました。関数名はuploadFilesとしています。
import json
import boto3
import base64
import io
from datetime import datetime
import cgi
BUCKET_NAME='mybucket22021015'
DIRECTORY='uploadedfiles/'
s3 = boto3.resource('s3')
def lambda_handler(event, context):
bucket = s3.Bucket(BUCKET_NAME)
body = base64.b64decode(event['body-json'])
#body = event['body']
fp = io.BytesIO(body)
environ = {'REQUEST_METHOD': 'POST'}
headers = {
'content-type': event['params']['header']['content-type'],
'content-length': len(body)
}
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('アップロード完了')
}
API gatewayの作成
関数URLではなくAPIgatewayを使用します。
-
アクションからメソッドの作成。作成されたフィールド右端の下向き三角みたいな記号をクリックするとメソッドを選択できる。クライアント側からのデータを取得できるようにPOSTを選択する。フィールド横のチェックマークをクリック
動作確認1
動作確認はGoogleChrome拡張機能のTalend API Testerを用いました。
下記のように入力した後に、Sendボタンを押します。
ここまでの設定ではうまくいきませんでした。Content-Type:multipart/form-dataで受け取れるようにするにはAPI gatewayでマッピングテンプレートを設定する必要があるようです。
API gateway マッピングテンプレートの設定
-
次いで、「メソッドリクエストのパススルー」を選択するとテンプレートが自動入力されます。特に編集しないまま保存ボタンをクリックしましょう。
-
これでマッピングテンプレートの設定は完了です。念の為、再度デプロイしました。
動作確認2
動作確認1と同様にテストしましたが、やはりエラーとなりました。エラーメッセージは、
string argument should contain only ASCII characters
とのこと。
API gateway バイナリメディアタイプの設定
さらにAPI gatewayの設定が必要でした。
1.API gatewayのナビゲーションバーより、「設定」をクリック
動作確認3
まだエラーとなります。エラーメッセージは、
An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
lambdaからS3を操作する権限がないので怒られている感じですね。
lambda ロールの設定
-
許可を追加ボタンからポリシーをアタッチすることができます。「インラインポリシーを作成」からの方がわかりやすいかと思います。
-
「インラインポリシーを作成」をクリック後に現れる画面で、サービスにS3を選択します。アクションについては、今回はListBucket、GetObject、PutObjectの3つを設定しました。
-
各アクションの対象となるリソースを指定する必要があります。予め準備しておいたS3バケットを設定します。
バケットの設定は下記のようにバケット名(今回はtestbucket)
オブジェクトの設定は、今回はtestbucket以下すべてとしました。
動作確認4
以上の設定で、任意のファイルをlambda経由でS3にアップロードできることが確認できました。