S3にアップロードされたファイルがzipならlambdaで自動解凍する

#やりたいこと
S3にアップしたファイルがzipかどうかを判別して、自動的にunzipする処理をlambdaで実行します。
圧縮のサンプルはよく見かけるけど、解凍のサンプルがあまり無い気がしたので、利用シーンは正直まったく浮かばないけど作ってみました。

#手順
1. S3にアップロード用のバケットを作成。
2. 解凍ファイルの保存先用のバケットも作成。（1と同じバケットでもOK）
3. lambda作成
以上。

#サンプルコード
##使用モジュール
以下のモジュールを使用しています。
- **async**:　フロー制御用のモジュール
- **node-zip**:　zipを操作出来るモジュール
- **mime-types**:　ファイル名からいい具合にcontentTypeを判断してくれるモジュール

##補足
* S3にputObjectするにはcontentTypeの指定が必要なので、mime-typesを使っていますが、この子は判断できないファイルの場合に"false"を返す仕様みたいなので、その時は強制的に 'application/octet-stream' にしちゃってます。
* zipの中身を1ファイルずつ非同期処理しつつも、全ファイルの保存が終了したタイミングで終わらせたかったので、asyncを使っています。
* 保存先は別バケットにしました。同一バケットだと、またこのラムダ君が実行されてしまうから、というだけの理由です。でももし、zipファイルの中にさらにzipが…！みたいな、マトリョーシカ的なファイルが想定されるのであれば、同一バケットのほうが逆に良いかと思います。

```js:unzip.js
console.log('Loading event');
var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01'});
var node_zip = require('node-zip');
var mime = require('mime-types');
var async = require('async');

//解凍ファイルの保存先バケット名
var unzip_bucket = 'bucket-name';

//解凍したファイルの保存処理
function unzip_file(bucket, key, body, content_type, callback) {
    s3.putObject({
        Bucket: bucket,
        Key: key,
        Body: new Buffer(body, 'binary'),
        ContentType: content_type
    }, callback);
}

exports.handler = function(event, context) {
    console.log('Received event:');
    console.log(JSON.stringify(event, null, '  '));

    // Get the object from the event and show its content type
    var bucket = event.Records[0].s3.bucket.name;
    var key = event.Records[0].s3.object.key;
    s3.getObject({Bucket:bucket, Key:key},
        function(err,data) {
            if (err) {
                context.done(null, '');
                console.log('error getting object ' + key + ' from bucket ' + bucket +
                '. Make sure they exist and your bucket is in the same region as this function.');
                context.done('error','error getting file'+err);
            }
            else {
                //zipファイルかどうか判断
                if (data.ContentType == 'application/zip') {

                    var zip = new node_zip(data.Body, {base64: false, checkCRC32: true});

                    //zipの中身を1件ずつunzip
                    async.forEach(Object.keys(zip.files), function(i, next) {
                        var f = zip.files[i];
                        console.log(f.name);
                        var mimetype = mime.lookup(f.name);
                        if (mimetype == false) {
                            mimetype = 'application/octet-stream';
                        }
                        console.log(mimetype);
                        unzip_file(unzip_bucket, f.name, f.asBinary(), mimetype, function (err) {
                            if (err) {
                                context.done(err, "unzip error");
                            }
                            next();
                        });
                    }, function (err) {
                        if (err) {
                            context.done(err, "async forEach error");
                        }
                        console.log('finish');
                        context.done(null, '');
                    });

                }
                else {
                    console.log('not zip!');
                    context.done(null, '');
                }

            }
        }
    );
};
```

#未解決事項
ファイル名が日本語の時に文字化けする、という現象が発生しています。
こちらについては、後日修正したいと思います。

ところで、ラムちゃんどこ行った？