LoginSignup
8
5

More than 5 years have passed since last update.

ゼロから始めるLINEBot(AWS×node.js) ③投稿された画像をS3に保存

Last updated at Posted at 2017-12-03

前回の記事の続きです。
ゼロから始めるLINEBot(AWS×node.js)②オウム返しする
https://qiita.com/tenn25/items/498f768a58ba6a6de156

この記事で分かること

  • LINEに投稿された画像をS3に保存する

この記事の対象者

  • いろいろと初心者(自分がそうなので)
  • MessagingAPIのような外部APIを使ったことがない
  • AWSもあんま詳しくない(アカウントは持ってるくらい)

流れ

第1回 とりあえず動かす
1.LINE Developersの登録/設定
2.実装(Lambda/node.js)
3.定期実行の設定(CloudWatch)

第2回 オウム返しの実装
4.ドメイン取得,DNS設定,SSL証明書の設定(Route53/ACM/SNS/S3)
5.イベントの受け取り(APIGateWay)
6.ユーザへの返信(Lambda/node.js)

第3回 ユーザ情報や投稿画像の保存(この記事)
7.ストレージ(S3やDB)との連携

投稿画像の取得

投稿からS3保存までの流れは以下の通りです。
①ユーザがLINEに画像を投稿する。
②画像は一旦LINEサーバに保存され、WebHookによって、APIGateWayが叩かれる。
③APIGateWayの裏でLambdaが実行される。
④Lambdaの処理でLINEサーバへ画像を取得する。
⑤Lambdaの処理でS3に画像を保存する。

S3への保存ファイル名は「ユーザID/現在時刻.jpg」としようと思います。

LINEにメッセージが投稿されると、WebHookを通じてLambdaにリクエストが届きますが、
リクエストのevent.events[0].message.typeがimageであれば画像が投稿されたと判断できます。

画像は一旦LINE側のサーバに保存されているようなので、
https://api.line.me/v2/bot/message/{messageId}/content
に対してGETリクエストを投げる必要があります。

GETリクエストの結果をdataとしてバッファに流し込めばS3に転送できそうです。

index.js

var https = require('https');
var AWS = require('aws-sdk');

AWS.config.update({
    accessKeyId: process.env.AWS_S3_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_S3_SECRET_ACCESS_KEY,
    region: process.env.AWS_S3_REGION
});

exports.handler = (event, context, callback) => {

    //リクエストを取得
    event = event.events[0];
    var replyToken = event.replyToken;
    var message = event.message;
    var userId = event.source.userId;


    if(message.type === 'text'){
        //テキストが投稿された場合の処理はこちら

    }else if(message.type === 'image'){
        //画像が投稿された場合の処理はこちら
        var s3 = new AWS.S3();
        var message_id = message.id;

        //投稿された画像はmessage_idによって取得
        var send_options = {
            host: 'api.line.me',
            path: '/v2/bot/message/'+ message_id +'/content',
            headers: {
                "Content-type": "application/json; charset=UTF-8",
                "Authorization": " Bearer " + process.env.CHANNEL_ACCESS_TOKEN
            },
            method:'GET'
        };

        var data = [];

        //LINEサーバに対してリクエストを投げると画像(data)が取得できるのでS3に保存する
        var reqImg = https.request(send_options, function(res){
            res.on('data', function(chunk){
              data.push(new Buffer(chunk));
            }).on('error', function(e){
              console.log("ERROR: " + e.stack);
            }).on('end', function(){
                //ここらへんはPromiseで書いた方がいいかもしれない

                //ファイル名として現在時刻を取得
                var nowDate = new Date();
                var nowTime = nowDate.getTime();

                var params = {
                    Bucket: process.env.S3_BUCKET_NAME, // ←バケット名
                    Key: userId + '/' + nowTime + '.jpg', // ←バケットに保存するファイル名
                    Body: Buffer.concat(data)
                };
                s3.putObject(params, function(err, data) {
                    context.done();
                });
            });
        });
        reqImg.end();
    }
};

node.jsの話になってしまいますが、
④Lambdaの処理でLINEサーバへ画像を取得する。
⑤Lambdaの処理でS3に画像を保存する。
このへんが非同期処理になってしまうため、
④が完了してから⑤が開始するようになんらか工夫する必要ああります。(上記の書き方かPromiseを使うなど)

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