3

i am working on site where i am allowing users to download PDF files. Each PDF file is stored on server using random hash names, eg.

file
768E1F881783BD61583D64422797632A35B6804C.pdf 
is stored in
/usr/share/nginx/html/contents/7/6/8/E/1/768E1F881783BD61583D64422797632A35B6804C.pdf 

now i can try to give users the direct location of file , but the file name after its being downloaded is shown as 768E1F881783BD61583D64422797632A35B6804C.pdf and i would like to rename the file on the fly, i can achive this using php like this

<?php
// We'll be outputting a PDF  
header('Content-type: application/pdf');

// It will be called downloaded.pdf  
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// The PDF source is in original.pdf  
readfile('original.pdf');
?> 

ref: Rename pdf file to be downloaded on fly

but i am lloking for something nginx rules directly which can rewrite download urls to path and rename too on the fly.

How can i do so ?

i have tried something like this.

location ^/download-pdf {
    alias   /usr/share/nginx/html/contents;
if ($request_filename ~ ^.*?/[^/]*?_(.*?\..*?)$)
{
    set $filename $1;
}

add_header Content-Disposition 'attachment; filename=$filename';
}

so if i send user to this location

domain.com/download-pdf/768E1F881783BD61583D64422797632A35B6804C.pdf?title=this.is.test

then i want this file to be downloaded at users PC using title/filename as this.is.test.pdf

/usr/share/nginx/html/contents/7/6/8/E/1/768E1F881783BD61583D64422797632A35B6804C.pdf 

can this be done only using nginx rewrite rules ? or i need to use PHP too ?


update1:

i have tried using it like this

location ^/download-pdf/([0-9A-F])/([0-9A-F])/([0-9A-F])/([0-9A-F])/([0-9A-F])/([0-9A-F]+).pdf$ {
    alias   /usr/share/nginx/basesite/html/contents;
add_header Content-Disposition 'attachment; filename="$arg_title.pdf"'; 
}

but the accessing url gives 404 not found error.


update2:

tried with this

location ~ /download-pdf {
alias   /usr/share/nginx/html;
rewrite ^/download-pdf/([0-9a-fA-F])/([0-9a-fA-F])/([0-9a-fA-F])/([0-9a-fA-F])/([0-9a-fA-F])/([0-9a-fA-F]+).pdf$ /contents/$1/$2/$3/$4/$5/$6.pdf break;
add_header Content-Disposition 'attachment; filename="$arg_title.pdf"'; 
}

still getting 404 not found.

Community
  • 1
  • 1
  • 1
    You almost got it. Just no need for `if`. Just `add_header Content-Disposition 'attachment; filename="$arg_title.pdf"';` – Alexey Ten Jun 04 '15 at 17:25
  • @AlexeyTen need more info, still not working, how can i split the hash , and get first 5 characters for creating sub-directory structure ? thanks –  Jun 04 '15 at 19:02

1 Answers1

12

You can't use both alias and rewrite together if I remember correctly. Instead, just use a location regex match and those captures will be available to both the add_header and alias directives:

location ~* /download-pdf/([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F]+)\.pdf$ {
    add_header Content-Disposition 'attachment; filename="$arg_title"';
    alias   /usr/share/nginx/basesite/html/contents/$1/$2/$3/$4/$5/$1$2$3$4$5$6.pdf;
}

This will match this URL:

https://www.example.com/download-pdf/768E1F881783BD61583D64422797632A35B6804C.pdf?title=SamplePdf.pdf

And map it to this file path:

/usr/share/nginx/basesite/html/contents/7/6/8/E/1/768E1F881783BD61583D64422797632A35B6804C.pdf

Note: If someone wants to make that regex less ugly by all means go for it!

Chris Haas
  • 53,986
  • 12
  • 141
  • 274
  • I would replace `([0-9a-fA-F])` with simple `(.)`. And probably do it in rewrite rather than location – Alexey Ten Jun 05 '15 at 06:51
  • @AlexeyTen, can you `redirect` to files outside of `root` or would you need to declare that `internal`? – Chris Haas Jun 05 '15 at 21:42
  • Tou could declare any `root`, in location – Alexey Ten Jun 06 '15 at 08:17
  • @ChrisHaas is there something to make hash to lowercase inside location block of nginx config , as directories are in lowercase and i would like to pass hash in uppercase , thanks –  Jul 11 '15 at 02:58
  • If you have [embedded perl installed you can use this](http://stackoverflow.com/a/11170826/231316) or if you [have lua installed you can use this](https://dodwell.us/rewrite-uri-to-lowercase-using-nginxperl-nginxlua-or-apache/#lua-method). Otherwise, to the best of my knowledge, nginx doesn't have any native character transposition capabilities. – Chris Haas Jul 13 '15 at 13:28
  • Hey Chris, this worked for me, but this also causes auto-downloading when the pdf is opened by link. Are you aware of a way to set the download name without this side-effect (meaning that it is just opened in a browser until one saves it manually)? To be specific, I'm using the Vivaldi browser, haven't tested the behavior in others – YakovL May 11 '23 at 13:44
  • @YakovL, try changing `attachment` to `inline` – Chris Haas May 11 '23 at 14:00
  • Yeap, thanks, have already tried that and it worked! – YakovL May 12 '23 at 15:11