目的
S3に上がっている画像ファイルをリサイズしたい
→ Webサイトの画像DLの負荷を下げる、画面表示の高速化をする
Lamdaの実装
Lamdaの基本的な設定は端折ります。
S3にアップされたファイルを別のバケットにリサイズして作成するAPIを以下の通り実装。
!!同じバケットを指定すると無限実行されるので注意!!
index.js
index.js
var AWS = require('aws-sdk');
var gm = require('gm').subClass({ imageMagick: true });
var util = require('util');
var s3 = new AWS.S3();
exports.handler = function(event, context, callback) {
var bucket = event.Records[0].s3.bucket.name; // 変換元画像のバケット名
var key = event.Records[0].s3.object.key; // 変換元画像のキー名
var thumbnailBucket = bucket + "-thumbnail"; // 変換後画像のバケット名(ここでは末尾にthumbnailを付け足すことにしてある)
var thumbnailKey = key; // 変換後画像のキー名(ここでは変換前と同じにしてある)
// 拡張子を抽出
var typeMatch = key.match(/\.([^.]*)$/);
if (!typeMatch) {
callback("Could not determine the image type.");
return;
}
// 拡張子がjpg, jpeg, pngのものだけ許可する
var imageType = typeMatch[1];
if (imageType != "jpg" && imageType != "jpeg" && imageType != "png") {
callback('Unsupported image type: ${imageType}');
return;
}
// S3の画像にアクセス
s3.getObject({Bucket: bucket, Key: key}, function(err, data){
if (err) { context.done('error getting object', err); }
// ----- Icon用 -------
gm(data.Body)
.resize('40', null) // 40pxにする
.stream(function(err,stdout,stderr){ // ストリームで出力する
if(err){
context.fail(err);
}
var chunks = []; // ストリームのチャンクを溜め込むための配列
stdout.on('data',function(chunk){
chunks.push(chunk); // チャンクを溜め込む
});
stdout.on('end',function(){
var buffer = Buffer.concat(chunks); // 最後まで溜め込んだら結合してバッファに書き出す
gm(buffer).toBuffer(function(errs, buff){
var params = {
Bucket: thumbnailBucket,
Key: 'icon/'+thumbnailKey,
ContentType: imageType,
Body: buff
};
s3.putObject(params, function(err, data) { // S3に書き出す
if(err){
console.log("gm upload error");
context.fail(err);
}
context.succeed({
"error":false
});
});
});
});
stderr.on('data',function(data){
console.log('stderr data: ' + data);
});
}); // Icon Create End
});
};
gnu-sedのインストール
payload.jsonのファイル名を書き換えられるように以下インストール
$ brew install gnu-sed
invokeコマンドを連続実行するシェルスクリプトを書く
resize.sh
filename=$1
cat ${filename} | while read line
do
gsed -i -e "30c\\ \"key\": \"${line}\"," payload.json
aws lambda invoke --invocation-type Event --function-name {*lamdaName*} --region ap-northeast-1 --payload file:///Users/{userName}/develop/payload.json output.txt
echo ${line}
done
payload.jsonを作成する
payload.json
{
"Records":[
{
"eventVersion":"2.0",
"eventSource":"aws:s3",
"awsRegion":"ap-northeast-1",
"eventTime":"1970-01-01T00:00:00.000Z",
"eventName":"ObjectCreated:Put",
"userIdentity":{
"principalId":"AIDAJDPLRKLG7UEXAMPLE"
},
"requestParameters":{
"sourceIPAddress":"127.0.0.1"
},
"responseElements":{
"x-amz-request-id":"C3D13FE58DE4C810",
"x-amz-id-2":"FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"
},
"s3":{
"s3SchemaVersion":"1.0",
"configurationId":"testConfigRule",
"bucket":{
"name":"{バケット名}",
"ownerIdentity":{
"principalId":"A3NL1KOZZKExample"
},
"arn":"arn:aws:s3:::{バケット名}"
},
"object":{
"key": "{対象ファイル名 *シェルで書き換えらる}",
"size":1024,
"eTag":"d41d8cd98f00b204e9800998ecf8427e",
"versionId":"096fKKXTRTtl3on89fVO.nfljtsv6qko"
}
}
}
]
}
リサイズしたいファイルをtxtにまとめる
images.txt
user/file1.png
user/file2.png
user/file3.png
実行コマンド
$ . resize.sh images.txt
実行すると202
のステータスが返ってきますが、キューに送られただけで正常なので大丈夫です。
まずはLamda単体をテスト実行してから動かしていきましょう。