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


# 目的
S3に上がっている画像ファイルをリサイズしたい
　→ <b>Webサイトの画像DLの負荷を下げる、画面表示の高速化をする</b>

# Lamdaの実装

Lamdaの基本的な設定は端折ります。
S3にアップされたファイルを別のバケットにリサイズして作成するAPIを以下の通り実装。

<b>！！同じバケットを指定すると無限実行されるので注意！！<b>

## 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のファイル名を書き換えられるように以下インストール

```cmd
$ brew install gnu-sed
```

参考：[gnu-sedのインストール](https://qiita.com/akameco/items/804970cd6655e69cc537)

# 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
```

# 実行コマンド
```cmd
$ . resize.sh images.txt
```

実行すると<code>202</code>のステータスが返ってきますが、キューに送られただけで正常なので大丈夫です。

まずはLamda単体をテスト実行してから動かしていきましょう。

## 参考記事
* [画像のサムネイルを生成する [Node, GraphicsMagick]](http://qiita.com/komakomako/items/a33ff4e610e378d986ff)

* [[AWS] Lambdaを使ってS3の既存画像を全部リサイズする](http://techeten.xyz/1170)