Ricerca nel sito web

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).