如何将文件附件流式传输到 Node.js 中的响应?

All*_*ore 0 javascript node.js express

使用 node.js/Express.js,我想调用 API,将该调用的响应写入文件,然后将该文件作为客户端的附件提供。API调用返回正确的数据并且数据已成功写入文件;问题是,当我尝试将该文件从磁盘流式传输到客户端时,提供的文件附件是空的。这是我的路线处理程序的主体:

// Make a request to an 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);
Run Code Online (Sandbox Code Playgroud)

问题:

为什么响应只是向客户端返回一个空白文档?

注意事项:

C1。发生此问题是否是因为当最后一行尝试读取文件时写入过程尚未开始?

C1.a) createWriteStream 和 createReadStream 都是异步的这一事实是否不能确保 createWriteStream 在事件循环中先于 createReadStream ?

C2。难道是“数据”事件没有被正确触发?Pipe 不会为你抽象这个吗?

感谢您的输入。

imN*_*Iam 5

尝试这个 :

var writableStream = fs.createWriteStream('./tmp/predictions/prediction_1.csv',
{ defaultEncoding: 'utf8' })

request({
    url: 'http://localhost:5000/execute_least_squares',
     qs: query
}).pipe(writableStream);

//event that gets called when the writing is complete
writableStream.on('finish',() => {
    res.writeHead(200, {
    "Content-Type": "text/csv",
    "Content-Disposition" : "attachment; filename=" + 
    "prediction_1.csv"
});
    var readbleStream = fs.createReadStream('./tmp/predictions/prediction_1.csv')
   readableStream.pipe(res);
}
Run Code Online (Sandbox Code Playgroud)

您应该捕获两个流(写入和读取)的 on.('error') ,以便您可以返回合适的响应(400 或其他)。

欲了解更多信息:

阅读 Node.js 流文档

注意事项:

发生此问题是否是因为当最后一行尝试读取文件时写入过程尚未开始?

答:是的。或者另一种可能是请求尚未完成。

createWriteStream 和 createReadStream 都是异步的,这难道不能确保 createWriteStream 在事件循环中先于 createReadStream 吗?

答:根据我在文档中读到的内容,createWriteStream 和 createReadStream 是同步的,它们只返回 WriteStream/ReadStream 对象。

难道是“数据”事件没有被正确触发?Pipe 不会为你抽象这个吗?

答:如果你正在谈论这段代码:

request({
    url: 'http://localhost:5000/execute_least_squares',
    qs: query
}).pipe(fs.createWriteStream('./tmp/predictions/prediction_1.csv', 
   {defaultEncoding: 'utf8'}));
Run Code Online (Sandbox Code Playgroud)

它根据请求文档工作。如果您正在谈论其他事情,请更详细地解释一下。