Frage

Ich mache mich mit node.js zusammen und habe zwei Möglichkeiten zum Lesen einer Datei und zum Senden des Drahtes entdeckt, sobald ich festgestellt habe, dass sie existiert und den richtigen MIME -Typ mit Writhead gesendet habe:

// 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();
});

Gehen ich richtig davon aus, dass Fs.CreateReadStream eine bessere Benutzererfahrung bietet, wenn die fragliche Datei etwas Großes wie ein Video war? Es fühlt sich an, als wäre es weniger blockisch; Ist das wahr? Gibt es andere Vorgaben, Nachteile, Vorbehalte oder Gotchas, die ich wissen muss?

War es hilfreich?

Lösung

Ein besserer Ansatz, wenn Sie "Daten" an "write ()" und "schließen" an "End ()" anschließen wollen:

// 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)

Das read.pipe(write) oder sys.pump(read, write) Der Ansatz hat den Vorteil, dass auch die Durchflussregelung hinzugefügt wird. Wenn der Schreibstrom keine Daten nicht so schnell akzeptieren kann, wird der Lesestrom angegeben, um sich zurückzuziehen, um die Datenmenge zu minimieren, die im Speicher gepuffert wird.

Das flags:"r" und mode:0666 werden durch die Tatsache impliziert, dass es a ist FileReadStream. Das binary Die Codierung ist veraltet - wenn eine Codierung nicht angegeben ist, funktioniert es nur mit den Rohdatenpuffern.

Außerdem können Sie einige andere Leckereien hinzufügen, die Ihre Datei, die viel Slicker bedient, dazu bringen:

  1. Schnüffeln für req.headers.range und sehen Sie, ob es zu einer Zeichenfolge passt wie /bytes=([0-9]+)-([0-9]+)/. Wenn ja, möchten Sie einfach von diesem Standort von Start bis Ende streamen. (Fehlende Nummer bedeutet 0 oder "das Ende".)
  2. Hash the Inode- und Erstellungszeit des Status () in einen ETAG -Header. Wenn Sie einen Anforderungs-Header mit "If-None-Match" -Anfragen erhalten, der mit diesem Header übereinstimmt, senden Sie eine Rückseite A. 304 Not Modified.
  3. Überprüf den if-modified-since Kopfball gegen die mtime Datum des Statusobjekts. 304 Wenn es seit dem angegebenen Datum nicht geändert wurde.

Auch im Allgemeinen, wenn Sie können, eine Senden Sie eine Content-Length Header. (Du bist stat-Ne die Datei, also sollten Sie dies haben.)

Andere Tipps

fs.readFile lädt die gesamte Datei in den Speicher, wie Sie betont haben, während als fs.createReadStream Lesen Sie die Datei in Stücken der von Ihnen angegebenen Größe.

Der Client wird auch damit beginnen, Daten schneller zu empfangen fs.createReadStream wie es in Stücken so verschickt wird, wie es gelesen wird, während wie als fs.readFile Lesen Sie die gesamte Datei aus und senden Sie sie erst dann an den Client. Dies mag vernachlässigbar sein, kann aber einen Unterschied machen, wenn die Datei sehr groß ist und die Scheiben langsam sind.

Denken Sie jedoch darüber nach, wenn Sie diese beiden Funktionen auf einer 100 -MB -Datei ausführen, verwendet der erste 100 -MB -Speicher, um die Datei zu laden, während letztere nur höchstens 4 KB verwenden würde.

EDIT: Ich sehe wirklich keinen Grund, warum Sie verwenden würden fs.readFile Zumal Sie sagten, Sie werden große Dateien öffnen.

Wenn es sich um eine große Datei handelt, würde "ReadFile" den Speicher feststellen, da er den gesamten Dateiinhalt im Speicher puffern und Ihr System möglicherweise hängen kann. Während ReadStream in Stücken gelesen.

Führen Sie diesen Code aus und beobachten Sie die Speicherverwendung in der Leistungs -Registerkarte "Performance" des Task -Managers.

 var fs = require('fs');

const file = fs.createWriteStream('./big_file');


for(let i=0; i<= 1000000000; i++) {
  file.write('Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n');
}

file.end();


//..............
fs.readFile('./big_file', (err, data) => {
  if (err) throw err;
  console.log("done !!");
});

Tatsächlich werden Sie nicht "fertig sein !!" Botschaft. "ReadFile" könnte den Dateiinhalt nicht lesen, da der Puffer nicht groß genug ist, um den Dateiinhalt zu halten.

Verwenden Sie nun statt "ReadFile" ReadStream und überwachen Sie die Speicherverwendung.

Hinweis: Der Code wird vom Samer Buna -Knotenkurs auf Pluralsight genommen

Eine andere, vielleicht nicht so bekannt fs.readFile verglichen mit fs.createReadStream. Sie sollten dies testen, um zu überprüfen, was am besten funktioniert. Außerdem weiß ich, dass dies durch jede neue Version des Knotens besser geworden ist (dh der Garbage Collector ist mit solchen Situationen schlauer geworden).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top