javascript - Nginx node.js express download di file grandi si ferma a 1,08 GB
Ho questa app node.js gestita tramite proxy da Nginx (in produzione). Una route è qualcosa del genere:
exports.download = function(req, res){
var id = req.params.id;
if (id && id == 'latest')
{
res.download(config.items.release_directory+'/<1.6GB-file>.zip', function(err){
if (err) {
console.log(err);
} else {
// do something
}
});
}
else
{
res.redirect(301, '/');
}
};
Quindi, cliccando sulla route/URL corretta il browser inizia a scaricare il file grande ma poi si ferma sempre a 1,08 GB (il file è circa 1,6 GB), troncandolo.
Davvero non riesco a capire perché. Qualche idea?
MODIFICA: config.items.release_directory è una directory statica di Express dichiarata come:
app.use('/releases', express.static(path.join(__dirname, '..', 'releases')));
EDIT2: Durante lo sviluppo con grunt che serve direttamente l'app senza Nginx funziona bene.
RISOLTO: leggi i commenti qui sotto, il problema è la variabile proxy_max_temp_file_size in Nginx
Risposta n. 1
Qui la questione è la configurazione di nginx, non il codice nodejs.
nginx scrive file temporanei sul disco prima di inviarli al client, spesso è una buona idea disabilitare questa cache se il sito deve servire file statici di grandi dimensioni, con qualcosa tipo:
location / {
proxy_max_temp_file_size 0;
}
(nessun limite)
Risposta n. 2
Sconsiglio fortemente di impostare proxy_max_temp_file_size 0 poiché ciò avrà l'effetto di rimuovere qualsiasi buffer proxy per tutti i tuoi endpoint.
Questo significa che il tuo server applicazioni non sarà in grado di svuotare i dati della risposta in un buffer NGINX (dal quale il client a valle può leggere ogni volta che ha connettività sufficiente) e sarà rilasciato/sbloccato. Invece, il tuo server applicazioni aspetterà che il client (senza un proxy NGINX in mezzo) scarichi i dati.
In alternativa, potresti istruire il tuo proxy NGINX a non bufferizzare selettivamente i dati di risposta quando trasmetti in streaming i dati del tuo file zip per evitare eventuali problemi con il file temporaneo del buffer di NGINX che si riempie e interrompe i download in streaming (questa è stata la mia esperienza).
Puoi ottenere questo facendo qualcosa di simile al seguente nel tuo endpoint Node.js:
res.set('X-Accel-Buffering', 'no');
In questo modo i dati verranno trasmessi direttamente da Express ai client, ma solo per gli endpoint per i quali non vuoi che i dati di risposta vengano memorizzati nella cache (probabilmente i tuoi endpoint di streaming).
