patnz patnz - 2 months ago 11
Node.js Question

node.js. Problems saving requested zip file to disk

I'm having trouble saving a remote zip file to disk with with node.
I'm using

request
library to make requests. I want to request a zip file,
if the request is succesful write it to disk. I can't get a good combination of
correct error handling and writing the file.

I want to do the following :

request.get('https://example.com/example.zip', {
'auth': { 'bearer': accessToken },
}, function(error, response, body) {
// shortcircuit with notification if unsuccessful request
if (error) { return handleError() }
// I want to save to file only if no errors
// obviously this doesn't work because body is not a stream
// but this is where I want to handle it.
body.pipe(fs.createWriteStream('./output.zip'));
});


I know I can pipe the request directly as follows but I can't get decent error handling. The on error callback doesn't fire for 404s, and if I catch the request and throw an error if
!response.ok
the empty output file is still written to disk

request.get('https://example.com/example.zip', {
'auth': { 'bearer': accessToken },
})
.on('error', handleError)
.pipe(fs.createWriteStream('./output.zip'));

Answer

Instead of using body.pipe(), use response.pipe().

request.get('https://example.com/example.zip', {
  auth: {
    bearer: accessToken
  }
}, (err, res, body) => {
  if (res.statusCode !== 200) { // really should check 2xx instead
    return handleError();
  }
  res.pipe(fs.createWriteStream('./output.zip');
});

The downside here though is that the request module is going to buffer the full response. Easy fix... don't use the request module. http.get() is fine and is a drop-in replacement.

Also, I highly recommend checking out the request-promise module which has an option for failing on 404.