Nodejs 发送部分响应

Posted

技术标签:

【中文标题】Nodejs 发送部分响应【英文标题】:Nodejs send partial response 【发布时间】:2015-09-29 03:17:13 【问题描述】:

mongodb 集合中有 20,000 条记录。我将所有这些记录导出到 csv 中。我使用这个发送部分响应:

res.writeHead(200, 
                     "Content-Type": "application/csv",
                     "Content-disposition": "attachment; filename='import.csv'"
 );

res.write(data + '0', "binary");

以上代码分批执行 500 个。当所有记录都处理完毕后,我将结束使用此代码。

if (++responseCount == loopCount) 
  res.end();

但是我收到了这个错误:

发送后无法设置标头。

但我下载的文件有 500 条记录。

这是我的完整代码。

var exportData = function (req, res, next) 

var limit = 500;
var responseCount = 0;
var loopCount = 1;
var size = 30000;

//Get 500 records at one time
var getData = function (req, start, cb) 
    req.db.collection('items').find().skip(start).limit(limit).toArray(function (err, records) 
        if (err) throw err;
        cb(null, records);
    );
;

if (size > limit) 
    loopCount = parseInt(req.size / limit);

    if ((req.size % limit) != 0) 
        loopCount += 1;
    


for (var j = 0; j < loopCount; j++) 

    getData(req, limit * j, function (err, records) 

        if (err) throw err;

        records.forEach(function (record) 
            //Process record one by one
        );

        res.write(records);

        if (++responseCount == loopCount) 
            res.setHeader('Content-type', 'application/csv');
            res.setHeader("Content-disposition", 'attachment; filename="import.csv"');
            res.end();

        

    );

;

【问题讨论】:

你能展示你的完整代码吗?问题不在于你放在这里的东西。理想情况下足以运行并查看问题(模拟数据可能是个好主意)。 您在批处理操作完成之前发回响应。 问题现已解决。 ***.com/questions/31339652/… 显然,您在写入标头之前发送了数据。不管怎样,为什么不把你的答案标记为更正呢? 【参考方案1】:

为什么不直接流式传输数据?您可以使用猫鼬query.stream 功能。文档中的一个示例:

// follows the nodejs 0.8 stream api
Thing.find( name: /^hello/ ).stream().pipe(res)

流将为您处理数据流。作为 node.js 流,你也可以监听事件:

// manual streaming
var stream = Thing.find( name: /^hello/ ).stream();

stream.on('data', function (doc) 
  // do something with the mongoose document
).on('error', function (err) 
  // handle the error
).on('close', function () 
  // the stream is closed
);

【讨论】:

【参考方案2】:

此声明

res.writeHead(200, 
                     "Content-Type": "application/csv",
                     "Content-disposition": "attachment; filename='import.csv'"
 );

当您发送响应时属于标题部分。因此,它发送标题。 res.end() 也发送header。所以,这样你再次发送header。

请参考这个stackoverlflow问题 编辑代码:

data.pipe(resp);
resp.end();

更多请参考这个pipe

【讨论】:

即使这个条件没有被执行,我也得到了错误。【参考方案3】:
var exportData = function (req, res, next) 

    res.writeHead(200, 
        'Content-Type': 'application/csv',
        'Content-Disposition': 'attachment; filename="import.csv"'
    );

    var limit = 500;
    var responseCount = 0;
    var loopCount = 1;
    var size = 30000;

    //Get 500 records at one time
    var getData = function (req, start, cb) 
        req.db.collection('items').find().skip(start).limit(limit).toArray(function (err, records) 
            if (err) throw err;
            cb(null, records);
        );
    ;

    if (size > limit) 
        loopCount = parseInt(req.size / limit);

        if ((req.size % limit) != 0) 
            loopCount += 1;
        
    

    for (var j = 0; j < loopCount; j++) 

        getData(req, limit * j, function (err, records) 

            if (err) throw err;

            records.forEach(function (record) 
                //Process record one by one
            );

            res.write(records);

            if (++responseCount == loopCount) 
                res.end();
            

        );
    
;

【讨论】:

提交答案时,请在您的代码中添加一些解释。 是 write 立即发送数据,作为部分响应,还是将数据写入缓冲区,等待发送?

以上是关于Nodejs 发送部分响应的主要内容,如果未能解决你的问题,请参考以下文章

NodeJS静态文件访问性能测试

如何发送 jpeg 的多部分响应

将大型响应 Json 作为多部分数据或多个部分发送

当内容类型为“text/xml”时,Axis2 发送多部分响应

HttpClient发送请求后得到的响应内容出现部分乱码的问题

使用 NodeJS 进行多部分文件上传