質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Q&A

解決済

1回答

3440閲覧

node.jsで保存した画像が開けなくなることについて

akihir

総合スコア39

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

0グッド

0クリップ

投稿2019/05/05 15:09

編集2019/05/22 07:40

現在、linebotに送信された画像をnode.jsでoutフォルダに保存するというプログラムを組み立てています。
以下のコードを用いるとoutフォルダにはtest.jpgというデータで保存することができました。
しかし、test.jpgをwindowsフォトビューアで開いてみると「ファイルが破損しているか、大きすぎる可能性があります。」とエラーが表示されます。

https://qiita.com/nbapps_dev/items/d9c689a61cc5dd8440ee
https://qiita.com/PianoScoreJP/items/8b477a2bb09dd1db7826

いくつかのサイトを参考にしてエンコーディングを変えたりしてみましたが、やはり開くことができないファイルのままでした。

ちなみに作成されたtest.jpgは、ディスク上のサイズが0バイトであり、ファイルが破損している可能性が考えられます。
アドバイスよろしくお願いします。

以下のコードでは、★部分が問題となるfs.writefile()となっています。

JavaScript

1'use strict'; 2const fs = require('fs'); 3const bodyParser = require('body-parser'); 4const express = require('express'); 5const line = require('@line/bot-sdk'); 6const PORT = process.env.PORT || 3000; 7const config = { 8 channelSecret: '適切なものを記入', 9 channelAccessToken: '適切なものを記入' 10}; 11const app = express(); 12 13app.post('/webhook', line.middleware(config), (req, res) => { 14 console.log(req.body.events); 15 Promise 16 .all(req.body.events.map(handleEvent)) 17 .then((result) => res.json(result)); 18}); 19 20const client = new line.Client(config); 21 22function handleEvent(event) { 23 if (event.type !== 'message' || event.message.type !== 'text') { 24 return ★fs.writeFile("./out/test.jpg",event.message.image,"binary",(error)=>{ 25 if(error){ 26 console.log("error"); 27 } 28 }); 29 } 30 return client.replyMessage(event.replyToken, { 31 type: 'text', 32 text: event.message.text //実際に返信の言葉を入れる箇所 33 }); 34} 35 36app.listen(PORT); 37console.log(`Server running at ${PORT}`);

(追記)

getMessageContentを使用して以下のように★付近のコードを変更しました。

python

1 2if (event.message.type == "image"){ 3 4 return client.getMessageContent(event.message.id).then((stream) => { 5 stream.on('data', (chunk) => { 6 //console.log(chunk); 7 fs.writeFile("./out/test.jpg",chunk,"binary",(error)=>{ 8 if(error){ 9 console.log("error"); 10 } 11 }) 12 }) 13}) 14 15

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

event.message.type === "image"の場合(画像を受け取った場合)、
画像ファイルはevent.message.imageに直接画像が入ってくるわけではありません。
そのため、0バイトの画像が作成されているのかと思います。
https://developers.line.biz/ja/reference/messaging-api/#wh-image

LINEのトーク画面から普通に画像ファイルを送った場合は、コンテンツ取得APIを使用して画像本体を取得します。
https://developers.line.biz/ja/reference/messaging-api/#get-content

nodeのSDKを使用している場合は、
https://line.github.io/line-bot-sdk-nodejs/api-reference/client.html#methods
client.getMessageContent()に、event.message.idを指定することでreadable streamが取得できますので、それを元に画像の書き込みを行うと良いでしょう。

追記

getMessageContent() のマニュアルにもある通り、

Please beware that what it returns is promise of readable stream. You can pipe the stream into a file, an HTTP response, etc.

getMessageContent()のcallbackで返ってくるのはreadable streamです

ある程度の大きさの画像の場合、stream.on('data')は、chunkに分けられて複数回呼び出されます。

javascript

1stream.on('data', (chunk) => { 2 console.log(`Received ${chunk.length} bytes of data.`); 3});

のようにして見れば、何度も呼び出されているのがわかると思います。

コードを変えても0バイトの画像が出力されます。

何度も呼び出されますので、最後に呼び出されたものしか書き込まれていないのでしょう。
(なので、正確には0バイトではなく数バイトにはなってると思いますが壊れた画像になっているはずです。)

Node.js Stream を使いこなす - Qiita

こちらを参考に、fs.writeFile()を使うのではなく、fs.createWriteStream()で作成したWriteable Streamにpipeしてやれば動作するはずです。

javascript

1const dest = fs.createWriteStream('./out/test.jpg', 'binary'); 2client.getMessageContent(event.message.id).then(stream => { 3 stream.pipe(dest); 4})

投稿2019/05/21 14:30

編集2019/05/22 08:35
sansaisoba

総合スコア241

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akihir

2019/05/22 07:36

とても参考になるご回答どうもありがとうございます。 ただコードを変えても0バイトの画像が出力されます。 変更したコードは質問に追記しておきます。お手数ですがコメントよろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問