Serve large file with PHP and nginx X-Accel-Redirect
nginx, php
Solution
Ok - there's a couple of issues here:
1) Puting root inside of a location is a BAD IDEA according to the nginx developers.
2) The internal URL used for telling Nginx that this is an internal redirect shouldn't be exposed to users.
3) I can't see where your download.php file is being served from, so I changed your root location block to use try_files so a request to /download.php would be served by that file rather than index.php.
Your project should be laid out as:
project\
html - this is the root of your website
protected - this directory is not accessible directly
And your Nginx conf should look like:
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
root /path/to/project/html;
location / {
try_files $uri /index.php?$args;
}
location /protected_files {
internal;
alias /path/to/project/protected;
}
}
}
It's a good idea not to re-use the same names to mean different things as it's quite confusing. I've changed them so that now `protected` just refers to the actual physical directory that holds the files you want to serve. `protected_files` is just a string that allows Nginx to match the request from the x-accel header.
The only thing that needs changing in your PHP code is to use the correct string to allow Nginx to pickup the internal location:
$aliasedFile = '/download/real-pdf-file.pdf'; //this is the nginx alias of the file path
$realFile = '/path/to/project/protected/real-pdf-file.pdf'; //this is the physical file path
$filename = 'user-pdf-file.pdf'; //this is the file name user will get
header('Cache-Control: public, must-revalidate');
header('Pragma: no-cache');
header('Content-Type: application\pdf');
header('Content-Length: ' .(string)(filesize($realFile)) );
header('Content-Disposition: attachment; filename='.$filename.'');
header('Content-Transfer-Encoding: binary');
header('X-Accel-Redirect: '. $aliasedFile);
exit(0);
Problem
Hi I want user to be able to download PDF file from my server (Windows) configured with nginx PHP. This is my nginx.conf (server block) ``` http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; server { listen 80; server_name localhost; location / { root html; index index.php; } location /download { internal; alias /protected; } } } ``` ..and the PHP file (header part) ``` $file = '/download/real-pdf-file.pdf'; //this is the physical file path $filename = 'user-pdf-file.pdf'; //this is the file name user will get header('Cache-Control: public, must-revalidate'); header('Pragma: no-cache'); header('Content-Type: application\pdf'); header('Content-Length: ' .(string)(filesize($file)) ); header('Content-Disposition: attachment; filename='.$filename.''); header('Content-Transfer-Encoding: binary'); header('X-Accel-Redirect: '. $file); ``` The file is call from URL like this: ``` download.php?id=a2a9ca5bd4a84294b421fdd9ef5e438ded7fcb09 ``` I've try few example/solution from here but so far none is working. The file is large (between 250 to 400 MB each) and each user will be able to download 4 files. There is no issue with downloading part using PHP, only the nginx configuration that seem not working. No error log detected.