公式ドキュメントでは gm でサムネイルを作っているが node-imagemagick が入っているのでそのまま貼れば一応動く。
node-imagemagick はメンテされてないので gm を使ったほうがいいとは思う。
元画像用のバケットと、そのバケット名に -thumbnail
のサフィックスを付けたサムネイル用バケットが必要。
S3 バケットを作る
バケットとファンクションは同じリージョンに作る必要がある。
今回は US Standard に作った。
Lambda ファンクションを作る
Lambda function code
handler
var fs = require('fs');
var im = require('imagemagick');
var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01'});
exports.handler = function(event, context) {
console.log(JSON.stringify(event, null, 2));
console.log(JSON.stringify(context, null, 2));
var bucket = event.Records[0].s3.bucket.name;
var key = event.Records[0].s3.object.key;
s3.getObject({
Bucket: bucket,
Key: key,
IfMatch: event.Records[0].s3.object.eTag
}, function(err,data) {
if (err) {
context.done('error getting object', err);
} else {
console.log(data);
var contentType = data.ContentType;
var extension = contentType.split('/').pop();
im.resize({
srcData: data.Body,
format: extension,
width: 256
}, function(err, stdout, stderr) {
if (err) {
context.done('resize failed', err);
} else {
var thumbnailBucket = bucket + "-thumbnail";
var thumbnailKey = key.split('.')[0] + "-thumbnail." + extension;
s3.putObject({
Bucket: thumbnailBucket,
Key: thumbnailKey,
Body: new Buffer(stdout, 'binary'),
ContentType: contentType
}, function(err, res) {
if (err) {
context.done('error putting object', err);
} else {
console.log(JSON.stringify(res, null, 2));
context.done();
}
});
}
});
}
});
};
Execution role
Lambda がファンクション実行時に使う権限を定義する。
access-policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:*"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
trust-policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
その他
メモリやタイムアウトの設定はデフォルトのまま。
S3 の通知先に登録する
Lambda コンソールから Configure event source ボタンを押下。
先ほど作ったバケットを選択し Create/Select Role ボタンを押下。
Invocation Role を作成/選択する。
access-policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": [
"*"
]
}
]
}
trust-policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringLike": {
"sts:ExternalId": "arn:aws:s3:::*"
}
}
}
]
}