【问题标题】:How do I stream a file attachment to a response in node.js?如何将文件附件流式传输到 node.js 中的响应?
【发布时间】:2017-06-05 17:08:19
【问题描述】:

使用 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);

问题:

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

注意事项:

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

C1.a) createWriteStream 和 createReadStream 都是异步的事实是否不能确保在事件循环中 createWriteStream 将在 createReadStream 之前?

C2。会不会是“数据”事件没有被正确触发?不把这个抽象出来给你吗?

感谢您的意见。

【问题讨论】:

    标签: javascript node.js express


    【解决方案1】:

    试试这个:

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

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

    更多信息:

    Read the Node.js Stream documentation

    注意事项:

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

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

    createWriteStream 和 createReadStream 都是异步的事实是否不能确保在事件循环中 createWriteStream 将在 createReadStream 之前?

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

    会不会是“数据”事件没有被正确触发?不把这个抽象出来给你吗?

    A:如果你说的是这段代码:

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

    它根据请求文档工作。如果您在谈论其他内容,请更详细地解释它。

    【讨论】:

    • 感谢您的详细回复。您的代码可以工作,只是响应需要在“完成”事件处理程序中发送,否则您会尝试将标头写入已发送的响应。
    猜你喜欢
    • 2011-01-25
    • 1970-01-01
    • 2012-06-18
    • 1970-01-01
    • 2017-05-09
    • 2016-04-11
    • 2020-11-28
    • 1970-01-01
    • 2018-02-19
    相关资源
    最近更新 更多