write readfilesync node example node.js

node.js - readfilesync - fs write stream node js



fs.createWriteStream no crea inmediatamente el archivo? (3)

He hecho una descarga simple desde la función http como se muestra a continuación (el manejo de errores se omite para simplifcation):

function download(url, tempFilepath, filepath, callback) { var tempFile = fs.createWriteStream(tempFilepath); http.request(url, function(res) { res.on(''data'', function(chunk) { tempFile.write(chunk); }).on(''end'', function() { tempFile.end(); fs.renameSync(tempFile.path, filepath); return callback(filepath); }) }); }

Sin embargo, como llamo a download() decenas de veces de forma asíncrona, rara vez informa de un error en fs.renameSync quejándose de que no puede encontrar el archivo en tempFile.path .

Error: ENOENT, no such file or directory ''xxx''

Usé la misma lista de URL para probarlo, y falló un 30% de las veces. La misma lista de direcciones URL funcionó cuando se descargó una por una.

Probando un poco más, descubrí que el siguiente código

fs.createWriteStream(''anypath''); console.log(fs.exist(''anypath'')); console.log(fs.exist(''anypath'')); console.log(fs.exist(''anypath''));

no siempre se imprime true , pero a veces la primera respuesta se imprime false .

fs.createWriteStream que demasiadas llamadas fs.createWriteStream asíncronas no pueden garantizar la creación del archivo. ¿Es esto cierto? ¿Hay algún método para garantizar la creación de archivos?


Aquí está lo que yo uso para hacerlo:

function download(url, dest) { return new Promise((resolve, reject) => { http.get(url, (res) => { if (res.statusCode !== 200) { var err = new Error(''File couldn/'t be retrieved''); err.status = res.statusCode; return reject(err); } var chunks = []; res.setEncoding(''binary''); res.on(''data'', (chunk) => { chunks += chunk; }).on(''end'', () => { var stream = fs.createWriteStream(dest); stream.write(chunks, ''binary''); stream.on(''finish'', () => { resolve(''File Saved !''); }); res.pipe(stream); }) }).on(''error'', (e) => { console.log("Error: " + e); reject(e.message); }); }) };


La respuesta aceptada no descargó algunos de los últimos bytes para mí.
Aquí hay una versión de Q que funciona correctamente (pero sin el archivo temporal).

''use strict''; var fs = require(''fs''), http = require(''http''), path = require(''path''), Q = require(''q''); function download(url, filepath) { var fileStream = fs.createWriteStream(filepath), deferred = Q.defer(); fileStream.on(''open'', function () { http.get(url, function (res) { res.on(''error'', function (err) { deferred.reject(err); }); res.pipe(fileStream); }); }).on(''error'', function (err) { deferred.reject(err); }).on(''finish'', function () { deferred.resolve(filepath); }); return deferred.promise; } module.exports = { ''download'': download };

Tenga en cuenta que estoy escuchando para finish el flujo de archivos en lugar de end con la respuesta.


No debe llamar a write en su tempFile escritura tempFile hasta que haya recibido el evento ''open'' del stream. El archivo no existirá hasta que vea ese evento.

Para su función:

function download(url, tempFilepath, filepath, callback) { var tempFile = fs.createWriteStream(tempFilepath); tempFile.on(''open'', function(fd) { http.request(url, function(res) { res.on(''data'', function(chunk) { tempFile.write(chunk); }).on(''end'', function() { tempFile.end(); fs.renameSync(tempFile.path, filepath); return callback(filepath); }); }); }); }

Para su prueba:

var ws = fs.createWriteStream(''anypath''); ws.on(''open'', function(fd) { console.log(fs.existsSync(''anypath'')); console.log(fs.existsSync(''anypath'')); console.log(fs.existsSync(''anypath'')); });