【aws/api gateway/lambda/s3】 api gateway ⇔ lambda ⇔ s3 で、動的に画像のresize lambdaでのresize編
目次
lambdaの実装
speeeの方を参考にしつつ
- S3から画像を取得 image magicで画像をresize resizeした画像をs3にアップロード *画像のbinaryデータを返す
を実装する
resizeパラメーターは 全体像編でも書いたが
* endpoin_url/300/s3_info
* endpoin_url/300x300/s3_info
* endpoin_url/crop200x200+370+370/s3_info
reizeするための api URLの例は
endpoin_url/crop200x200+370+370/bucket_name/image/1/hogehoge.png
こんな感じでくるので、抜き出す必要あり
実際のコードがこちら
lambdaとうことで、node.js
'use strict'; const im = require('imagemagick'); const aws = require('aws-sdk'); const fs = require('fs'); const s3 = new aws.S3({ apiVersion: '2006-03-01' }); const TMP_INPUT_FILE_PATH = '/tmp/inputFile'; const CONVERTED_TMPFILE_NAME = '/tmp/converted_tmpfile'; exports.handler = (event, context, callback) => { var key_array = event.parameter.split('/'); key_array.splice(0,1); key_array.splice(-2,1); // 元画像のパスを取得 const key = key_array.join('/'); const bucket = event.parameter.split('/')[0] ; const params = { Bucket: bucket, Key: key, }; // 元画像のファイル形式を取得 var reg=/(.*)(?:\.([^.]+$))/; var file_type_match = key.match(reg); event.outPutName = event.parameter.split('/').slice(1).join('/'); event.outPutFileExtension = file_type_match[2]; // resize用のパラメーター取得 var reisze_params = event.parameter.split('/')[event.parameter.split('/').length - 2].split('-'); var size = ''; var crop = ''; var gravity = ''; var match = ''; for (var i = 0; i < reisze_params.length; i++) { if (!size) { match = reisze_params[i].match(/^\d*%?x?\d*%?[\^!<>@]?$/i); if (match) { size = match[0]; continue; } } if (!crop) { match = reisze_params[i].match(/^crop(\d+x\d+\+\d+\+\d+)$/i); if (match) { crop = match[1]; continue; } } if (!gravity) { match = reisze_params[i].match(/^(NorthWest|North|NorthEast|West|Center|East|SouthWest|South|SouthEast)$/i); if (match) { gravity = match[0]; continue; } } } console.log(size); console.log(crop); console.log(gravity); var convertParams = []; convertParams.push(TMP_INPUT_FILE_PATH); convertParams.push('-auto-orient'); if (size) { convertParams.push('-resize'); convertParams.push(size); } if (gravity) { convertParams.push('-gravity'); convertParams.push(gravity); } if (crop) { convertParams.push('-crop'); convertParams.push(crop); convertParams.push("+repage"); } convertParams.push(CONVERTED_TMPFILE_NAME); console.log(convertParams) s3.getObject(params, (err, data) => { if (err) { console.log(err); const message = `Error getting object ${key} from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`; console.log(message); callback(message); } else { fs.writeFile(TMP_INPUT_FILE_PATH, new Buffer(data.Body, 'binary'), (err) => { if (err) { callback(err, err.stack); } // ここでresize im.convert(convertParams, function (err, stdout, stderr) { if (err) { callback(err, 'im convert'); } console.log('adsfadsfasdfasdfasdfasdfasdfasdfasdfasdfadsfs'); fs.readFile(CONVERTED_TMPFILE_NAME, function (err, converted_data) { if (err) { callback(err, converted_data, 'converted tempfile read'); } console.log(bucket); console.log(event.outPutName); // resizeした画像をS3に上げる s3.putObject({ Bucket: bucket, Key : event.outPutName, Body : new Buffer(converted_data, 'binary'), ContentType: data.ContentType }, function (err, res) { if (err) { callback(err, 's3 putObject'); } // URLを返す場合はこちら // callback(null, event.outPutName) // binary dateを返す callback(null, new Buffer(converted_data, 'binary').toString('base64')) // これがないと、S3に上げる前に、lambdaが終わっちゃう context.done(); }); }); }); }); } }); };
テスト
lambda上でテストする場合は下記
{ "parameter": "bucket_name/folder_name1/folder_name2/600x600/hogehoge.jpg" }
性能
10MBくらいの画像でも、5秒くらいは一応返してくれる