Node.js:ストリームをバッファに読み込むには?
質問
私は与えられたURLから画像をダウンロードし、それをリサイズしてS3にアップロードする非常に簡単な関数を書きました(「gm」と「knox」を使用)、私はバッファへのストリームの読み取りを正しく行っているかどうか全く分かりません。(全て動作していますが、正しい方法なのでしょうか?)
また、私はイベントループについて何かを理解したいのですが、関数の1つの呼び出しが何かを漏らしたり、すでに実行中の別の呼び出しに 'buf' 変数を変更しないことをどのように知ることができますか(またはこのシナリオはコールバックが匿名関数であるので不可能ですか)?
var http = require('http');
var https = require('https');
var s3 = require('./s3');
var gm = require('gm');
module.exports.processImageUrl = function(imageUrl, filename, callback) {
var client = http;
if (imageUrl.substr(0, 5) == 'https') { client = https; }
client.get(imageUrl, function(res) {
if (res.statusCode != 200) {
return callback(new Error('HTTP Response code ' + res.statusCode));
}
gm(res)
.geometry(1024, 768, '>')
.stream('jpg', function(err, stdout, stderr) {
if (!err) {
var buf = new Buffer(0);
stdout.on('data', function(d) {
buf = Buffer.concat([buf, d]);
});
stdout.on('end', function() {
var headers = {
'Content-Length': buf.length
, 'Content-Type': 'Image/jpeg'
, 'x-amz-acl': 'public-read'
};
s3.putBuffer(buf, '/img/d/' + filename + '.jpg', headers, function(err, res) {
if(err) {
return callback(err);
} else {
return callback(null, res.client._httpMessage.url);
}
});
});
} else {
callback(err);
}
});
}).on('error', function(err) {
callback(err);
});
};
どのように解決するのですか?
全体として、あなたのコードで壊れるようなものは何も見当たりません。
2つの提案です。
あなたが組み合わせている方法
Buffer
オブジェクトを組み合わせる方法は、'data' イベントごとに既存のデータをすべてコピーしなければならないので、最適とは言えません。チャンクを配列にして
concat
を使う方が良いでしょう。
var bufs = [];
stdout.on('data', function(d){ bufs.push(d); });
stdout.on('end', function(){
var buf = Buffer.concat(bufs);
})
パフォーマンスのために、私はあなたが使っているS3ライブラリがストリームをサポートしているかどうかを調べます。理想的には、1つの大きなバッファを作成する必要は全くなく、単に
stdout
ストリームを直接S3ライブラリに渡すのが理想的です。
質問の2番目の部分に関しては、それは可能ではありません。関数が呼び出されると、その関数は独自のプライベートコンテキストを割り当てられ、その内部で定義されたすべてのアイテムは、その関数内で定義された他のアイテムからしかアクセスできなくなります。
更新
ファイルをファイルシステムにダンプすれば、おそらく 1 リクエストあたりのメモリ使用量は少なくなりますが、ファイル IO はかなり遅くなる可能性があるため、その価値はないかもしれません。この機能のプロファイリングとストレス テストができるようになるまでは、あまり最適化しない方がよいと思います。ガベージコレクタがその仕事をしている場合、最適化しすぎている可能性があります。
とはいえ、とにかくもっと良い方法があるので、ファイルを使用するのはやめましょう。必要なのは長さだけなので、すべてのバッファを一緒に追加する必要なく計算できますので、新しいバッファを割り当てる必要はまったくありません。
var pause_stream = require('pause-stream');
// Your other code.
var bufs = [];
stdout.on('data', function(d){ bufs.push(d); });
stdout.on('end', function(){
var contentLength = bufs.reduce(function(sum, buf){
return sum + buf.length;
}, 0);
// Create a stream that will emit your chunks when resumed.
var stream = pause_stream();
stream.pause();
while (bufs.length) stream.write(bufs.shift());
stream.end();
var headers = {
'Content-Length': contentLength,
// ...
};
s3.putStream(stream, ....);
関連
-
[解決済み] Node.jsのプログラムにコマンドライン引数を渡すにはどうしたらいいですか?
-
[解決済み] Node.jsを使うタイミングをどう判断するか?
-
[解決済み] Node.jsで終了する方法
-
[解決済み] Node.jsでファイルを書き込む
-
[解決済み] Node.jsアプリケーションをデバッグするにはどうすればよいですか?
-
[解決済み] Node.jsを完全にアンインストールして、最初から再インストールする方法 (Mac OS X)
-
[解決済み] Node.jsのmodule.exportsの目的と使い方を教えてください。
-
[解決済み] Node.jsで環境変数を読み込む
-
[解決済み] Node.jsでファイル/ディレクトリが存在するかどうかを同期的にチェックする
-
[解決済み] Node.jsのnpmモジュールをアンインストールするにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】MongoClient v3.0使用時、db.collectionは関数ではない
-
[解決済み】 console.logの出力をどこに永久保存するか?
-
[解決済み】モジュール 'internal/util/types' が見つかりません。
-
[解決済み】エラー TRK0005: 位置特定に失敗しました。"CL.exe"
-
[解決済み】Heroku + node.jsのエラー(Webプロセスが起動後60秒以内に$PORTにバインドできなかった)。
-
[解決済み】npm 5で作成されたpackage-lock.jsonファイルはコミットするのでしょうか?
-
[解決済み] エラーメッセージ MongoError: bad auth URI 文字列で認証に失敗しました。
-
[解決済み] ランタイム 'node' が PATH で見つからない - Visual Studio Code と Node.js
-
[解決済み] エラーです。Cannot find module 'ejs'
-
[解決済み] バルク更新を行う。