3

Node.js + request を使用してリモート ファイルをロードする方法を理解しているので、それを読み取って png バイナリ blob を返すことができます。1回のリクエスト(またはワンライナーでさえ)でそれを行うエレガントな方法はありますか

何かのようなもの:

http.createServer(function(req, res) {
    res.writeHead(200, {
        'Content-Type': 'image/png'
    });
    var picWrite = fs.createWriteStream(local);
    var picFetch = fs.createReadStream(local);
    picStream.on('close', function() {
        console.log("file loaded");
    });
    request(remote).pipe(picWrite).pipe(picFetch).pipe(res);
})

明確にするために、私の目的は、CDN からリモート ファイルをロードし、ローカルにサーバーにキャッシュしてから、元の要求でファイルを返すことです。将来のリクエストfs.exists()では、最初に存在することを確認するために使用します。


これはこれまでの私の最善の努力です:

http.createServer(function(req, res) {
    var file = fs.createWriteStream(local);
    request.get(remote).pipe(file).on('close', function() {
        res.end(fs.readFileSync(local), 'binary');
    });
})
4

1 に答える 1

7

リクエストは読み取り可能なストリームを返すため、そのdataおよびendイベントをリッスンして、HTTP レスポンスと書き込み可能なストリームの両方に書き込むことができます。

var http = require('http');
var request = require('request');

http.createServer(function(req, res) {
  res.writeHead(200, { 'Content-Type': 'image/png' });
  var file = fs.createWriteStream(local);

  // request the file from a remote server
  var rem = request(remote);
  rem.on('data', function(chunk) {
    // instead of loading the file into memory
    // after the download, we can just pipe
    // the data as it's being downloaded
    file.write(chunk);
    res.write(chunk);
  });
  rem.on('end', function() {
    res.end();
  });
});

あなたが示した方法は、最初にデータをディスクに書き込み、次にそれを再びメモリに読み込みます。データはディスクに書き込まれているときにすでにアクセス可能であるため、これはかなり無意味です。

イベント ハンドラーを使用すると、HTTP 応答とファイル ストリームの両方に書き込むことができ、無意味にファイルをメモリに再度読み込む必要がなくなります。これは、読み取り可能なストリームからデータを消費し、一度しか実行できないpipe()ため、を使用する際の問題も解決します。pipe()

これにより、メモリ不足の問題も解決されます。これは、大きなファイルをダウンロードすると、Node.js プロセスが事実上メモリ不足になるためです。ストリームでは、ファイルのチャンクのみが一度にメモリにロードされるため、この問題は発生しません。

于 2013-10-08T01:32:37.473 に答える