Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nodejs send partial response

There are 20,000 records in mongodb collection. I am exporting all these records in a csv. I am send partial response using this :

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

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

Above code is executing in batch of 500. I am ending using this code when all records are processed.

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

But I got this error :

Can't set headers after they are sent.

But I get the file downloaded with 500 records.

Here is my full code.

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

        }

    });
}
};
like image 607
Rohit Avatar asked Jul 10 '15 11:07

Rohit


2 Answers

Why not just stream the data? You could use mongoose query.stream feature. An example from the docs:

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

The stream will take care of the data flow for you. As a node.js stream, you can also listen for events:

// 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
});
like image 176
Rodrigo Medeiros Avatar answered Nov 09 '22 03:11

Rodrigo Medeiros


This statement

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

belongs to header section when you response is send.So,it send header.
res.end() also send header.So, in this way you sending header again.

Please refer this one stackoverlflow question


EDIT CODE :

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

Please refer this one for more pipe

like image 28
RIYAJ KHAN Avatar answered Nov 09 '22 01:11

RIYAJ KHAN