LoginSignup
113
109

More than 5 years have passed since last update.

S3に画像をアップロードしたらLambdaでサムネイルを生成する(node-imagemagick)

Last updated at Posted at 2014-12-03

公式ドキュメントでは 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:::*"
        }
      }
    }
  ]
}
113
109
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
113
109