Monday, 5 June 2017

How do I stream a file attachment to a response in node.js?

Using node.js/Express.js, I would like to make a call to an API, write the response of that call to a file, then serve that file as an attachment to the client. The API call returns the correct data and that data is successfully being written to file; the issue is that when I try and stream that file from disk to the client, the file attachment that gets served is empty. Here is the body of my route handler:

// Make a request to a 3rd party api, then pipe the response to a file. (This works)
request({
  url: 'http://localhost:5000/execute_least_squares',
  qs: query
}).pipe(fs.createWriteStream('./tmp/predictions/prediction_1.csv', 
  {defaultEncoding: 'utf8'}));

// Add some headers so the client know to serve file as attachment  
res.writeHead(200, {
    "Content-Type": "text/csv",
    "Content-Disposition" : "attachment; filename=" + 
    "prediction_1.csv"
});

// read from that file and pipe it to the response (doesn't work)
fs.createReadStream('./tmp/predictions/prediction_1.csv').pipe(res);

Is this issue happening because, by the time the last line tries to read the file, the async process of writing it hasn't begun? Doesn't the fact that createWriteStream and createReadStream are both async ensure that createWriteStream will precede createReadStream in the event loop? Could it be that the 'data' event is not being triggered correctly? Doesn't pipe abstract this away for you?

Thanks for your input.



via Allen More

No comments:

Post a Comment