Nginx fails to send full file from Node/Express app

Go To StackoverFlow.com

2

Sending large files (1.5gb) to a client with a connection speed < 2mbps results in the browser only receiving 1.08gb of data, but believing the download to be complete. Faster connections receive the full 1.5gb file.

My Express.js app figures out which file to send and responds with the response#download method:

app.get('/download-the-big-file', function(request, response) {
  var file = {
    name: 'awesome.file',
    path: '/files/123-awesome.file'
  };

  response.header("X-Accel-Redirect: " + file.path);

  response.download(file.path, file.name);
});

Notice that I set the X-Accel-Redirect header to leverage NginxXsendfile

My Nginx configuration:

server {

    client_max_body_size 2g;
    server_name localhost;

    location / {
        proxy_pass http://127.0.0.1:8000/;
    }

    location /files {
        root /media/storage;
        internal;
    }
}
2012-04-03 22:43
by tbeseda


3

I believe the original issue stems from Node (probably sending large files inside Node's I/O loop), and my assumption that Nginx was taking the download from Node properly was incorrect. I had a couple mistakes that meant NginxXSendfile wasn't working, and Node was still handling the response.

I had a syntax error:
To set response headers this is the correct syntax:

response.header('X-Accel-Redirect', file.path);

The body of the response should not be set when using the above header (doh!).
With Express/Connect/Node just #send the response with the X-Accel-Redirect header and set the Content-Disposition with response#attachment:

response.attachment(file.name);
response.send();
2012-04-05 20:29
by tbeseda


0

I had to add a Content-Disposition to response headers in addition to X-Accel-Redirect

Express.js code:

app.get('/files/test.txt', function (req, res) {
  res.setHeader('X-Accel-Redirect', '/files/test.txt');
  res.attachment('text.txt');
  res.send();
});

Nginx congif file (/etc/nginx/sites-available/default)

server {

    location /files {
      internal;
      root   /home/user;
    }
}

This serves the file test.txt, in /home/user/files (i.e. /home/user/files/test.txt).

2016-02-12 16:58
by K.A.D.