patnz
patnz

Reputation: 1141

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'));

Upvotes: 1

Views: 795

Answers (1)

Brad
Brad

Reputation: 163612

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.

Upvotes: 2

Related Questions