Content disposition header on Nginx

7,263

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 the file.ext form, send back the Content-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 a Content-Disposition: header with the filename= portion set the file.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.

Share:
7,263

Related videos on Youtube

user160301
Author by

user160301

Updated on September 18, 2022

Comments

  • user160301
    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
      Admin over 11 years
      Please, provide output of curl --head http://…/your/file.ext.
    • Admin
      Admin over 11 years
      As 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
    user160301 over 11 years
    Thank 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
    hrunting over 11 years
    The answer to 'custom HTTP headers for static files with Django' has an example of how to add a Content-Disposition: header for a file.