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.
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:
And your Nginx conf should look like:
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:
Based from recommendation and solution from Danack and some clarification from Carsten, I found that in Windows Serve, we need to set the full path in the alias like this:
Please note that the extra forward slash is needed (in my case, Windows 7 Pro on development, Windows Server 2008 for deployment). The only issue is now I need to test concurrent downloads to see if server resources is hogging.
I'm new with nginx, since it seem really faster that I switch from Apache. Thanks guy for the enlightenment! I'am glad to be part of Stackoverflow community :)