Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js request download file sometimes empty or no existing

I'm writing a downloader with node.js and the request module. Using the stream syntax I'm doing

var r = request(url).pipe(fs.createWriteStream(targetPath));
r.on('error', function(err) { console.log(err); });
r.on('finish', cb);

to download the file, save it and call the callback. However, in almost 50% of the cases the file is either empty or not created at all. No error event is emitted. It seems like the finish event is triggered even though the file wasn't (completely) written yet.

Context: The whole thing is wrapped into async.each calls.

Any clues? Thanks!

like image 993
Daniel Torres Avatar asked Jul 11 '13 08:07

Daniel Torres


People also ask

Why is this empty object in node?

this is empty because as noted above it is a reference to the same object as exports , which is to be populated by the developer. If this. module was a reference to module , then since this is a reference to exports , it would export the module itself along with the other exported items.

How do I force download node JS?

We can use the http GET method to fetch the files that are to be downloaded. The createWriteStream() method from fs module creates a writable stream and receives the argument with the location of the file where it needs to be saved.

Why request is deprecated node?

Request isn't really deprecated. It's no longer considering new features or breaking changes, but it is still being maintained. It's safe to use for the foreseeable future, but how good an idea it is to use it is up to the developer.


1 Answers

You need to close the file before accessing it:

var file = fs.createWriteStream(targetPath);
var r = request(url).pipe(file);
r.on('error', function(err) { console.log(err); });
r.on('finish', function() { file.close(cb) });

Incidentally, if the url replies with any http error (such as a 404 not found), that won't trigger the 'error' event, so you should probably check that separately:

function handleFailure(err) { console.log(err); };

var file = fs.createWriteStream(targetPath);
request(url, function(error, response) {
    if (response.statusCode != 200) {
        console.log("oops, got a " + response.statusCode);
        return
    }
    // close is async, and you have to wait until close completes otherwise
    // you'll (very rarely) not be able to access the file in the callback.
    file.on('finish', function() { file.close(cb) });

    response.pipe(file).on('error', handleFailure)
    file.on('error', handleFailure)
}).on('error', handleFailure);
like image 124
Augusto Roman Avatar answered Oct 18 '22 00:10

Augusto Roman