LoginSignup
4
5

More than 3 years have passed since last update.

LamdaでS3に上がっている画像を一括でリサイズする(ローカルから実行可能)

Posted at

目的

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

参考: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単体をテスト実行してから動かしていきましょう。

参考記事

4
5
2

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
4
5