Content disposition header on Nginx
nginx isn't going to know it needs to return the header just because the header was return from Apache. The request to Apache is going to return that header, but you're also telling the client to go fetch that file from nginx, and nginx isn't going to receive that header nor know to send it back unless you have something in the nginx configuration to do that.
Here's the way it's working now (...
represents other headers unimportant to this discussion):
Request to Apache
GET /your/file.ext HTTP/1.1
Host: apache.mysite.com
...
Response from Apache
HTTP/1.1 302 Redirect
Location: http://nginx.mysite.com:8080/fileid
Content-Disposition: attachment; filename="filename"
...
When your web client receives this, it's basically being told to go somewhere else. That's going to initiate a new request:
Request to nginx
GET /fileid HTTP/1.1
Host: nginx.mysite.com
...
Response from nginx
HTTP/1.1 200 OK
... (no Content-Disposition header)
You need to have the nginx response return the Content-Disposition
header, not the Apache/PHP response. You have a few options here:
- Pass the nginx request through to a script that will translate the
fileid
form to thefile.ext
form, send back theContent-Dispotion:
header and return the data (this is very similar to your PHP script, except it also needs to return the file data). - Request the
file.ext
form from nginx and configure nginx to always add aContent-Disposition:
header with thefilename=
portion set thefile.ext
of the request. - Update your PHP script to proxy the nginx request internally, so that rather than returning the
Location:
header and subsequent redirect, it returns the header it needs, then fetches the data from nginx internally and dumps it out to the client.
The second option seems cleanest to me, but your setup may not support it.
Related videos on Youtube
user160301
Updated on September 18, 2022Comments
-
user160301 almost 2 years
I am doing a setup where Apache runs the web application and NginX serves files that users download. The files should be downloaded with their real names instead of the names their are being stored with. The real names are retrieved from a database. I do not understand why am I failing to force NginX to download the files with their real names. I send the following headers in php from Apache to NginX:
header('Location: ' . "http://nginx.mysite.com:8080/" . $file['upload_id']); header('Content-type: ' . $this->mime); header('Content-Disposition: attachment; filename="' . $file['file_name'] . '"'); header('Last-Modified: ' . date('D, d M Y H:i:s \G\M\T' , $this->data_mod));
It looks like NginX ignores the content-disposition header? Or am I failing in the syntax?
Edit:Output of
curl --head http://…/your/file.ext
is as follows:
HTTP/1.1 200 OK Server: nginx/1.0.5 Date: Sat, 16 Feb 2013 14:26:33 GMT Content-Type: application/octet-stream Content-Length: 38807550 Last-Modified: Sun, 06 Jan 2013 14:37:36 GMT Connection: keep-alive Accept-Ranges: bytes
-
Admin over 11 yearsPlease, provide output of
curl --head http://…/your/file.ext
. -
Admin over 11 yearsAs you see, nginx is not sending it.
Content-Disposition
is not a standard header. It could be filtered inside Apache or nginx due to security considerations. Try to disable all security modules (mod_security?) temporary and check again.
-
-
user160301 over 11 yearsThank you very much for your response! I would like to go with the second option. Could you be that kind to tell me what exactly should I put in the Nginx config file to allow it to always add a content-disposition header?
-
hrunting over 11 yearsThe answer to 'custom HTTP headers for static files with Django' has an example of how to add a
Content-Disposition:
header for a file.