0

I have a storage where files are stored with filename corresponding to their MD5 hash. The files are stored like this:

...
/srv/storage/25/
/srv/storage/25/25D6D1AD130E4EB7D11F6AB48C09414E
...
/srv/storage/DF/
/srv/storage/DF/DF35407C5E433B5644538B41C957ABCE
...

The extra directories are just to prevent single root directory size blowing up.

These files are of various types; text files, PDF files, XLS files, anything goes. I'm serving these files over web interface that lists the files with real human file names that link to the HTTP file server. To make it easy for users to open these files from browser (Firefox) in appropriate application the web application appends file extension to the MD5 file name in file server URL so that browser can infer appropriate handler based on the filename extension. So for instance file report2017.pdf in the web interface links to

http://corp.biz/files/DF35407C5E433B5644538B41C957ABCE.pdf

which with the help of rewriting defined below will serve file:

/srv/storage/DF/DF35407C5E433B5644538B41C957ABCE

I use this location in my Nginx site to rewrite the URL to the correct path in the filesystem:

    location /files {
        root /srv/storage;
        rewrite '^/files/([0-9A-F]{2})([0-9A-F]{30}).*$' /$1/$1$2 break;
    }

Awesome! It works. Except that now Nginx replies with Content-Type: application/octet-stream for any URL under /files. Is there any way to make Nginx resolve MIME type before the rewrite?


The problem with Content-Type: application/octet-stream is that for PDF files even though the filename in URL ends with .pdf, Firefox for some reason goes straight to Save File dialog instead of letting users open it in a PDF viewer. This only happens on boxes where PDF file type is set to Preview in Firefox.

1
  • please review my answer below – gbolo May 9 '20 at 10:59
-1

I just tried this for fun and it worked:

    location /files {
      root   /usr/share/nginx/html;
    }

    location ~ "^/files/([0-9a-fA-F]{2})([0-9a-fA-F]{30})(.*)$" {
        return 301 $scheme://$http_host/files/$1/$1$2$3;
    }

Looks like you forgot to include the 3rd part (ext). This should also work:

    location /files {
      root   /usr/share/nginx/html;
      rewrite '^/files/([0-9a-fA-F]{2})([0-9a-fA-F]{30})(.*)$' /files/$1/$1$2$3 break;
    }
2
  • This doesn't work because the latter rewrites to non-existent path. I didn't forget to include 3rd part because the files don't have any extension as I wrote at the beginning of the post. The former does the same. – woky May 9 '20 at 12:44
  • oh i see, in that case i dont think nginx can detect content type without the extension, you will have to help it out. Why dont you try and preserve extensions, at least only for pdf? – gbolo May 9 '20 at 17:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.