2015-07-10 10 views
5

Ci sono 20.000 record nella raccolta mongodb. Sto esportando tutti questi record in un CSV. Sono inviare risposta parziale utilizzo di questo:Nodejs invia risposta parziale

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

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

Sopra codice è in esecuzione in lotto di 500. Sto finendo di utilizzare questo codice quando tutti i record vengono elaborati.

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

Ma ho ottenuto questo errore:

Impossibile impostare le intestazioni dal loro invio.

Ma ottengo il file scaricato con 500 record.

Ecco il mio codice completo.

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

     } 

    }); 
} 
}; 
+0

Potete mostrare il codice completo? Il problema non è in quello che hai messo qui. Idealmente sufficiente per correre e vedere il problema (il mocking dei dati potrebbe essere una buona idea). –

+0

Si sta rinviando la risposta prima che l'operazione batch sia terminata. – bluesman

+0

Il problema è risolto ora. http://stackoverflow.com/questions/31339652/nodejs-send-partial-response/31398864#31398864 – Rohit

risposta

1

Questa affermazione

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

appartiene intestazione sezione quando si risposta è send.So, it invia intestazione.
res.end() inviare anche header.So, in questo modo si invia di nuovo l'intestazione.

prega di fare riferimento questo stackoverlflow domanda


CODICE EDIT:

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

prega di fare riferimento questo uno per più pipe

+0

Ho ricevuto un errore anche quando questa condizione non è stata eseguita. – Rohit

2

Perché non solo lo streaming dei dati? È possibile utilizzare la funzione mangusta query.stream. Un esempio dei documenti:

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

Lo stream si prenderà cura del flusso di dati per voi. Come un flusso node.js, è anche possibile ascoltare per eventi:

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

     }); 
    } 
}; 
+1

Quando si inviano risposte, aggiungere alcune spiegazioni al codice. – MayorMonty

+0

Infatti. Qualche spiegazione del codice dovrebbe essere in ordine. – MoshMage

+0

La scrittura scriverà istantaneamente i dati, come una risposta parziale, o scriverà i dati su un buffer, in attesa di essere inviati? –