78 votes

Quels sont les avantages et les inconvénients de fs.createReadStream vs fs.readFile dans node.js?

Je nettoie avec node.js et nous avons découvert deux manières de lire un fichier et de l'envoyer sur le réseau, une fois que j'ai établi qu'il existe et ont envoyé le bon type MIME avec writeHead:

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

Suis-je raison de supposer que la fs.createReadStream pourrait fournir une meilleure expérience à l'utilisateur si le fichier en question a été quelque chose de grand, comme une vidéo? Il se sent comme il peut être moins bloc-ish, est-ce vrai? Existe-il d'autres avantages, les inconvénients, les mises en garde, ou de pièges j'ai besoin de savoir?

62voto

isaacs Points 6050

Une meilleure approche, si vous êtes juste de s'accrocher "les données" pour "write()" et "fermer" pour "mettre fin()":

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

L' read.pipe(write) ou sys.pump(read, write) approche a l'avantage de l'ajout de flux de contrôle. Donc, si l'écriture de flux ne peut pas accepter des données aussi rapidement, il le dira à la lecture de flux à l'arrière, de façon à minimiser la quantité de données à arriver en mémoire tampon.

L' flags:"r" et mode:0666 sont sous-entendues par le fait que c'est un FileReadStream. L' binary enconding est obsolète -- si l'encodage n'est pas spécifié, il va tout simplement travailler avec les données brutes des tampons.

Aussi, vous pouvez ajouter quelques autres goodies qui ferons de votre service de fichiers d'un ensemble beaucoup plus lisse:

  1. Sniff pour req.headers.range et voir si elle correspond à une chaîne comme /bytes=([0-9]+)-([0-9]+)/. Si donc, vous voulez juste de le diffuser que du début à la fin de l'emplacement. (Il manque le nombre moyen de 0 ou de "la fin".)
  2. Hachage de l'inode et le temps de création de la stat() appeler dans un en-tête ETag. Si vous obtenez une demande d'en-tête avec des "si-none-match" correspondant à celle de l'en-tête, envoie une 304 Not Modified.
  3. Vérifier l' if-modified-since tête contre l' mtime date sur l'état de l'objet. 304 si ce n'était pas modifiée depuis la date prévue.

Aussi, en général, si vous le pouvez, envoyez un entête Content-Length. (Vous êtes statting le fichier, de sorte que vous devrait l'avoir.)

47voto

Christian Joudrey Points 2603

fs.readFile va charger tout le fichier en mémoire comme vous l'avez souligné, alors que, en fs.createReadStream va lire le fichier en morceaux de la taille que vous spécifiez.

Le client sera également commencer à recevoir des données plus rapidement en utilisant fs.createReadStream comme il est envoyé en morceaux en cours de lecture, alors que, en fs.readFile va lire le fichier en entier et ensuite seulement commencer à envoyer au client. Ce pourrait être négligeable, mais il peut faire une différence si le fichier est très gros et que les disques sont lents.

Pensez à ce que, si vous exécutez ces deux fonctions sur un fichier de 100 mo, la première utilisation de 100 mo de mémoire pour charger le fichier, tout comme cette dernière est utilisée seulement à plus de 4 ko.

Edit: je ne vois pas pourquoi vous auriez fs.readFile surtout depuis que vous avez dit que vous allez l'ouverture des fichiers volumineux.

0voto

Un autre, peut-être pas si bien connu chose, c'est que je crois que le Nœud est préférable de nettoyer les non-utilisation de la mémoire après l'utilisation de fs.readFile par rapport à l' fs.createReadStream. Vous devriez tester pour vérifier ce qui fonctionne le mieux. Aussi, je sais que, chaque nouvelle version de Nœud, ce qui a eu mieux (c'est à dire le garbage collector a devenir plus intelligent avec ces types de situations).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X