Nodejs发送部分响应

MongoDB收集中有2万条logging。 我在csv中导出所有这些logging。 我使用这个发送部分回应:

res.writeHead(200, { "Content-Type": "application/csv", "Content-disposition": "attachment; filename='import.csv'" }); res.write(data + '0', "binary"); 

上面的代码正在批量执行500.我将结束处理所有logging时使用此代码。

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

但是我得到这个错误:

发送后无法设置标题。

但是我得到的文件下载了500条logging。

这是我的完整代码。

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

为什么不直接传输数据呢? 你可以使用mongoosequery.streamfunction。 来自文档的示例:

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

该stream将为您处理数据stream。 作为一个node.jsstream,你也可以监听事件:

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

这个说法

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

当你的回应是发送的时候,它属于头部分,所以它发送头部。
res.end()也发送头。所以,这样你再次发送头。

请参阅这个stackoverflow的问题

编辑代码:

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

请参考这个更多的pipe道

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