Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nginx node.js express download big files stop at 1.08GB

I have this node.js app proxied by Nginx (on production). A route is something like this:

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

};

So, clicking the right route/URL the browser starts to download the big file but then it stops always at 1.08GB (the file is about 1.6GB), truncating it.

I really cannot understand why. Any ideas?

EDIT: The config.items.release_directory is a static Express directory declared as:

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

EDIT2: On development with grunt serving directly the app without Nginx it works fine.

SOLVED: read the comments below, problem is proxy_max_temp_file_size variable in Nginx

like image 407
michelem Avatar asked Jul 30 '14 14:07

michelem


2 Answers

Here the matter is nginx configuration, not nodejs code.

nginx write temp files in disk before sending them to the client, it's often a good idea to disable this cache if the site is going to serve big static files, with something like:

location / {
    proxy_max_temp_file_size 0;
}

(no limit)

like image 196
Rémi Becheras Avatar answered Nov 05 '22 10:11

Rémi Becheras


I strongly discourage setting proxy_max_temp_file_size 0 as this will have the effect of removing any proxy buffer for all your endpoints.

This means that your application server won't be able to flush response data into an NGINX buffer (from which the downstream client can read whenever it gets sufficient connectivity) and be released/unblocked. Instead your application server will be waiting for the client (no NGINX proxy in the middle) to download the data.

Alternatively, you could instruct your NGINX proxy to selectively not buffer response data when streaming your zipfile data to avoid any potential issues with NGINX's buffer tempfile getting full and interrupting streaming downloads (which was my experience).

You can achieve this by doing something like the following in your Node.js endpoint:

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

This way the data will be streamed directly from Express to clients but only for the endpoints for which you don't want response data buffered (most likely your streaming endpoint(s)).

like image 25
mecampbellsoup Avatar answered Nov 05 '22 11:11

mecampbellsoup