javascript - readfilesync - upload files with node js
¿Cuáles son los pros y los contras de fs.createReadStream vs fs.readFile en node.js? (4)
Otra cosa, quizás no tan conocida, es que creo que Node es mejor para limpiar la memoria no utilizada después de usar fs.readFile
comparación con fs.createReadStream
. Debe probar esto para verificar qué funciona mejor. Además, sé que con cada nueva versión de Node, esto ha mejorado (es decir, el recolector de basura se ha vuelto más inteligente con este tipo de situaciones).
Me estoy volviendo loco con node.js y he descubierto dos formas de leer un archivo y enviarlo por el cable, una vez que establezco que existe y he enviado el tipo MIME correcto con 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();
});
¿Estoy en lo cierto al suponer que fs.createReadStream podría proporcionar una mejor experiencia de usuario si el archivo en cuestión era algo grande, como un video? Se siente como si fuera menos bloqueado; ¿Es esto cierto? ¿Hay otros pros, contras, advertencias o errores que necesito saber?
Si se trata de un archivo grande, "readFile" acapararía la memoria ya que almacena todo el contenido del archivo en la memoria y puede colgar el sistema. Mientras ReadStream lee en trozos.
Ejecute este código y observe el uso de la memoria en la pestaña de rendimiento del administrador de tareas.
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 !!");
});
De hecho, no verás "hecho!" mensaje. "readFile" no podría leer el contenido del archivo ya que el buffer no es lo suficientemente grande como para contener el contenido del archivo.
Ahora, en lugar de "readFile", use readStream y monitorice el uso de la memoria.
Nota: el código se toma del curso del Nodo Samer buna en Pluralsight
Un mejor enfoque, si solo va a conectar "datos" a "escribir ()" y "cerrar" a "finalizar ()":
// 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)
El read.pipe(write)
o sys.pump(read, write)
tiene el beneficio de también agregar control de flujo. Por lo tanto, si la secuencia de escritura no puede aceptar datos tan rápido, le indicará a la secuencia de lectura que retroceda, a fin de minimizar la cantidad de datos almacenados en la memoria.
Las flags:"r"
y mode:0666
están implícitas por el hecho de que es un FileReadStream. El código binary
está en desuso: si no se especifica una codificación, simplemente funcionará con los almacenamientos intermedios de datos brutos.
Además, podría agregar algunos otros elementos que harán que su archivo sirva mucho más:
- Sniff para
req.headers.range
y ver si coincide con una cadena como/bytes=([0-9]+)-([0-9]+)/
. De ser así, solo desea transmitir desde esa ubicación de inicio a fin. (El número que falta significa 0 o "el final"). - Hash el inodo y el tiempo de creación de la llamada stat () en un encabezado ETag. Si obtiene un encabezado de solicitud con "if-none-match" que coincida con ese encabezado, envíe de vuelta un
304 Not Modified
. - Compruebe el encabezado
if-modified-since
contra la fechamtime
en el objeto stat. 304 si no fue modificado desde la fecha provista.
Además, en general, si puede, envíe un encabezado Content-Length. (Estás declarando el archivo, por lo que deberías tener esto).
fs.readFile
cargará todo el archivo en la memoria como usted señaló, mientras que fs.createReadStream
leerá el archivo en fragmentos del tamaño que especifique.
El cliente también comenzará a recibir datos más rápido utilizando fs.createReadStream
ya que se envía en fragmentos mientras se lee, mientras que fs.readFile
leerá todo el archivo y solo luego comenzará a enviarlo al cliente. Esto podría ser insignificante, pero puede marcar la diferencia si el archivo es muy grande y los discos son lentos.
Sin embargo, piense en esto, si ejecuta estas dos funciones en un archivo de 100MB, la primera usará 100MB de memoria para cargar el archivo mientras que este último solo usará como máximo 4KB.
Editar: realmente no veo ninguna razón por la que fs.readFile
especialmente porque dijiste que fs.readFile
archivos de gran tamaño.