1. ホーム
  2. javascript

node.jsのfs.createReadStreamとfs.readFileの長所と短所は何ですか?

2023-10-06 21:02:05

質問

私はnode.jsをいじくりまわしており、いったんファイルが存在することを確認し、writeHeadで適切なMIMEタイプを送信した後、ファイルを読み込んでワイヤーで送信する2つの方法を発見しました。

// read the entire file into memory and then spit it out

fs.readFile(filename, function(err, data){
  if (err) throw err;
  response.write(data, 'utf8');
  response.end();
});

// read and pass the file as a stream of chunks

fs.createReadStream(filename, {
  'flags': 'r',
  'encoding': 'binary',
  'mode': 0666,
  'bufferSize': 4 * 1024
}).addListener( "data", function(chunk) {
  response.write(chunk, 'binary');
}).addListener( "close",function() {
  response.end();
});

問題のファイルがビデオのような大きなものである場合、fs.createReadStreamはより良いユーザー体験を提供するかもしれないと仮定するのは正しいですか?それはブロック的でないかもしれないように感じますが、これは本当でしょうか? 私が知る必要のある他の長所、短所、注意点、または gotchas がありますか?

どのように解決するのですか?

より良い方法として、"write()"に"data"を、"end()"に"close"を引っ掛けるだけなら、以下の方法があります。

// 0.3.x style
fs.createReadStream(filename, {
  'bufferSize': 4 * 1024
}).pipe(response)

// 0.2.x style
sys.pump(fs.createReadStream(filename, {
  'bufferSize': 4 * 1024
}), response)

read.pipe(write) または sys.pump(read, write) アプローチには、フロー制御を追加する利点もあります。 つまり、書き込みストリームがそれほど速くデータを受け入れることができない場合、読み込みストリームに後退するように指示し、メモリにバッファリングされるデータ量を最小限に抑えます。

また flags:"r"mode:0666 であることは暗黙の了解です。 FileReadStream . は binary エンコーディングは非推奨です。エンコーディングが指定されない場合は、生のデータバッファで動作します。

また、ファイルサービスをよりスムーズにするために、他のグッズを追加することができます。

  1. をスニッフィングします。 req.headers.range のような文字列にマッチするかどうかを確認し /bytes=([0-9]+)-([0-9]+)/ . もしそうなら、その開始位置から終了位置までストリーミングしたいだけなのです。 (欠番は 0 または "終わり" を意味します。)
  2. stat()呼び出しからinodeと作成時間をETagヘッダーにハッシュ化します。 そのヘッダにマッチする "if-none-match" を持つリクエストヘッダを取得した場合、そのヘッダを返します。 304 Not Modified .
  3. を確認します。 if-modified-since ヘッダを mtime ヘッダを返します。 提供された日付以降に変更されていない場合は、304。

また、一般的に、可能であれば、送信時に Content-Length ヘッダを送信してください。 (あなたは stat -を付けているので、これがあるはずです)