0

I'm downloading a file from remote server using axios post method,then saving to the disk. Once the file is saved to disk I need to send it to client in response.

let response = await axios.post(url, body, {headers :headers, responseType:'stream'})
let filePath = "reports/" + response.headers['content-disposition'].split("filename=")[1].replace(/\"/g, "");
await response.data.pipe(fs.createWriteStream(filePath)) 
res.download(filePath);

The problem I'm facing is, Response is sent when the file writing is still in progress. If there is any alternative, Please suggest.

EDIT:- The problem was with the write stream.

Solution:-

let response = await axios.post(url, body, {headers :headers, responseType:'stream'});
let filePath = "reports/" + response.headers['content-disposition'].split("filename=")[1].replace(/\"/g, "");
let ws = fs.createWriteStream(filePath);
new Promise((resolve, reject) => {
ws.on('open', () => {
    response.data.pipe(ws);
}).on('error', function (err) {
    reject(res.send({error: "message"}));
}).on('finish', function () {
   ws.end();
   resolve(res.download(filePath));
 });
});

Link:- fs.createWriteStream does not immediately create file?

SurajKj
  • 706
  • 7
  • 13
  • When you say response is sent when the file is writing you mean a timeout event is sent?, if so you either need to increase your server timeout (this obv dosen't scale to infinity as files can be enormous) or you'll have to use a `socket` connection instead. – Tom Slabbaert Jun 03 '20 at 11:16
  • No, response is sent with file of 0 kb. It's working if I add add delay of 1 sec before sending the response. – SurajKj Jun 03 '20 at 12:40

2 Answers2

2

I think you should use Promise.All to resolve all promises before moving on.

Anshu Saurabh
  • 51
  • 1
  • 6
0

As much as i know response.data.pipe is not a promise so await is not going to work on it. Try :-

response.data.pipe(fs.createWriteStream(filePath), {end: false})
response.data.on('end', ()=> res.download(filePath))
Akshay Nailwal
  • 196
  • 1
  • 9