1. まとめ
クライアントからAPI GatewayにPOSTされたバイナリデータをLambdaで何かしらの処理を実施する方法を記載する.ここでは,実例としてバイナリデータとして画像ファイルを受け取り,Lambdaにて画像をS3に保存する方法を記載する.
2. 目次
- 1 まとめ
- 2 目次
- 3 簡易処理フロー
- 4 実装
- 4.1 Lambda
- 4.2 API Gateway
- 5 テスト
- 6 参考リンク
3. 簡易処理フロー
- API Gateway
- バイナリメディアタイプにてimage/*を設定しバイナリを扱えるよう設定
- Lambda
- Base64にエンコードされたデータをデコードし画像ファイルのバイナリーデータを取得
- 画像をS3に保存
- S3
- 画像を格納
4. 実装
下記のcURLで叩いて,S3に画像が保存されていればOK
$ curl -X POST -H 'Content-type: image/jpeg' --data-binary "@ramen.jpeg" https://xxxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/v1/upload
4.1. Lambda
コード全体
'use strict';
const aws = require('aws-sdk');
const s3 = new aws.S3({ apiVersion: '2006-03-01'});
exports.handler = (event, context, callback) => {
// add logging level
console.log = console.log.bind(null, '[LOG]');
console.info = console.info.bind(null, '[INFO]');
console.warn = console.warn.bind(null, '[WARN]');
console.error = console.error.bind(null, '[ERROR]');
// variables
var response = {}
// check event
console.log(event)
// if data is encoded with base64, then decode with base64 and save it in S3
if (event.isBase64Encoded === true) {
// decode
var decode = new Buffer(event.body,'base64');
// save data in s3
var params = {
Bucket: 's3-xxxxxxxxxxxxxxx-20180702',
Key: 'ramen.jpg',
ContentType: 'image/jpeg',
Body: decode
};
s3.putObject(params, function(err, data) {
if (err) {
console.error(err);
console.error('image upload failed');
// create response
response.statusCode = 400
response.body = JSON.stringify({
message: 'fail.'
})
callback(null, response);
} else {
console.log('image upload success');
// create response
response.statusCode = 200
response.body = JSON.stringify({
message: 'image has been uploaded to S3'
})
callback(null, response);
}
});
} else {
// create response
response.statusCode = 400
response.body = JSON.stringify({
message: 'fail.'
})
callback(null, response);
}
};
補足
eventの中身の確認
下記でCloudWatchにログとして書き出す
// check event
console.log(event)
下記が結果.重要な部分だけ抽出.
①event.body
がbase64でencodeされた画像データ
②event.isBase64Encoded
がtrueになっておりbase64でバイナリデータをエンコードされているのがわかる
body: '/9j/4AAQSkZJRgABAQAASABIAAD/99b06vJCFQ+N .. 省略 ... h/9k=',
isBase64Encoded: true
デコード
base64でエンコードされていることを確認し,デコードnew Buffer(event.body,'base64')
を実施
// if data is encoded with base64, then decode with base64 and save it in S3
if (event.isBase64Encoded === true) {
// decode
var decode = new Buffer(event.body,'base64');
4.2. API Gateway
バイナリメディアタイプを設定しない場合のレスポンス
$ curl -X POST -H 'Content-type: image/jpeg' --data-binary "@ramen.jpg" https://xxxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/v1/upload
{"message":"fail"}
バイナリメディアタイプにimage/*
を追加し変更を保存.ステージに反映するには再度APIをデプロイする必要がある.
バイナリメディアタイプを設定した場合のレスポンス
image/*
が登録されているため,image/jpeg
が通る.
$ curl -X POST -H 'Content-type: image/jpeg' --data-binary "@ramen.jpg" https://xxxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/v1/upload
{"message":"image has been uploaded to S3"}
適当にimage/*
以外にContent-typeを設定してみると,エラーになる.想定通りの挙動
$ curl -X POST -H 'Content-type: text/plain' --data-binary "@ramen.jpg" https://xxxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/v1/upload
{"message":"fail"}
Content-typeを外してみてもエラーになる.想定通りの挙動
$ curl -X POST --data-binary "@ramen.jpg" https://xxxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/v1/upload
{"message":"fail"}
5. テスト
cURLで叩いてみる
$ curl -X POST -H 'Content-type: image/jpeg' --data-binary "@ramen.jpg" https://xxxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/v1/upload
{"message":"image has been uploaded to S3"}
S3に保存されていることを確認
6. 参考リンク
なし