javascript - Nginx node.js express ladda ner stora filer stopp vid 1,08 GB


Jag har den här node.js-appen proxad av Nginx (i produktion). En rutt ser ut ungefär så här:

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

};

Så, när man klickar på rätt rutt/URL börjar webbläsaren ladda ner den stora filen men den stannar alltid vid 1,08 GB (filen är ungefär 1,6 GB), vilket kapar den.

Jag kan verkligen inte förstå varför. Några idéer?

REDIGERA: config.items.release_directory är en statisk Express-katalog deklarerad som:

app.use('/releases', express.static(path.join(__dirname, '..', 'releases')));

REDIGERA2: Vid utveckling med grunt som servar appen direkt utan Nginx fungerar det bra.

LÖST: läs kommentarerna nedan, problemet är variabeln proxy_max_temp_file_size i Nginx

Svar #1

Här handlar det om nginx-konfiguration, inte nodejs-kod.

nginx skriver temporära filer till disken innan de skickas till klienten, det är ofta en bra idé att stänga av denna cache om sidan ska leverera stora statiska filer, med något som:

location / {
    proxy_max_temp_file_size 0;
}

(ingen gräns)

Svar #2

Jag avråder starkt från att sätta proxy_max_temp_file_size 0 eftersom detta kommer att ha effekten att ta bort alla proxybuffertar för alla dina slutpunkter.

Detta innebär att din applikationsserver inte kommer att kunna tömma svarsdatan i en NGINX-buffert (från vilken den nedströms klienten kan läsa när den får tillräcklig anslutning) och bli frigjord/avblockerad. Istället kommer din applikationsserver att vänta på att klienten (ingen NGINX-proxy emellan) laddar ner datan.

Alternativt kan du instruera din NGINX-proxy att selektivt inte buffra svarsdatan när du strömmar dina zipfil-data för att undvika potentiella problem med att NGINX:s buffer-tillfälliga filer blir fulla och avbryter strömningsnedladdningar (vilket var min erfarenhet).

Du kan uppnå detta genom att göra något liknande följande i din Node.js-endpunkt:

res.set('X-Accel-Buffering', 'no');

På detta sätt kommer data att strömmas direkt från Express till klienter men endast för de slutpunkter för vilka du inte vill att svarsdatan ska buffras (troligtvis din/de strömningsslutpunkt(er)).