I recently needed to force a PDF to download using Apache. The default behaviour for most browsers is to try to open the PDF inside the browser itself. This is fine for a small PDF or for powerful machines - but a large PDF on even a modest machine can often lock the browser up. This needed fixing!
After 20 minutes of perusing the Apache documents, I happened across the FilesMatch option which takes Regular Expressions. Regular Expressions are cool things which pattern match; you give it a rather complicated (yet logical) pattern and it matches it for you. Initially I used something like this...
<Files *.pdf> ForceType application/pdf Header set Content-Disposition attachment </Files>
This worked PERFECTLY - except some files had upper-case extensions and some had lower and I could see situations in the future where combinations of upper and lower case would be used too - just to piss me off! Because of this, not even this would work...
<FilesMatch "\.(pdf|PDF)"> ForceType application/pdf Header set Content-Disposition attachment </FilesMatch>
That would match perfectly - as long as it was an EXACT match on upper OR lower case.
I was reaching the end of my patience - that is until I read the Using Character Classes on PerlDoc.
This showed me that I could force the RegEx (short for Regular Expressions) to match in a case-insensitive manner. This lead me to the following...
<FilesMatch "\.(?i:pdf)$"> ForceType application/pdf Header set Content-Disposition attachment </FilesMatch>
However this only worked in proper browsers - and the bulk of the world are sadistic enough to use Internet Explorer based ones. For some reason, if Internet Explorer see's the content type "Application/PDF" it will simply open it up in the reader. The solution? Why not pretend its a bog standard Octet Stream, just like a Zip file? After all, that's basically all it is; a binary file... A steam of bytes.
<FilesMatch "\.(?i:pdf)$"> ForceType application/octet-stream Header set Content-Disposition attachment </FilesMatch>
And there you have it… A perfectly working modification to force all PDF files to download - this will work for any file extensions you chose to put into the FilesMatch argument!
22 Comments
thanks
Hey! That worked perfectly, thanks! You might indicate that one needs mod_headers to use
Header set.mod_headers, nice tip!
Thanks for that... I didn't have a problem as my Apache configs tend to have everything enabled by default ;-)
Where to put it?
Do I put this code in the .htaccess file or what?
It can go anywhere
You can put this code in either the htaccess or the vhost configuration for your server.
You can read more about FilesMatch at the Apache Document page.
Hey, great explanation. I'd
Hey, great explanation. Thanks for the well written explanation and for the code sample(s).
Force PHP Download
Really Interesting document, but how would you use that if apache is a proxyserver?
Hi, I can't get this to
Hi,
I can't get this to work in .htaccess, I asked around and someone said that the regex was wrong.
Any idea how I can get it to work?
For this technique applied
For this technique applied to other web servers and languages such as PHP, check out http://www.stuvel.eu/pdfdownload ;-)
Thanks! Just what I was
Thanks!
Just what I was looking for ;)
Force .PDF Download
I've been trying to do this for 6 months. Worked perfectly. I love you, sir (platonically)
Great!
This is just what i was lokking for! Thanks for the explanation! I will be linking to your post :-)
Thanks, the Internet Explorer
Thanks, the Internet Explorer specific Header Set and RegEx tip really helped!
Three cheers!
Thanks a bunch! Works like a charm, you spared us all a headache :)!!!
I just copy and paste to
I just copy and paste to .htaccess file, but getting internal error. Do you have any idea what would be wrong?
Error Logs
You'd probably need to check your error logs. Maybe an apache extension isn't enabled?
something is wrong ...
I try to use this trick to open a download window from the browser instead of displaying an image.
it works in Mozilla, but not on IE. the mod_headers module is enabled ...
Modification
I'm horrible at regular expressions; How could I modify that to force download of all file types? I have a folder full of different file types for clients to download, and this would save them time.
No FilesMatch
You'd simply put the 2 main lines into a .htaccess file in that folder; no need to files match. Bear in mind, and HTML files in there (such as index.html) may also start to download to...
NOTE: I've not tried this - it's an educated guess...
Thanks for solution, regular
Thanks for solution,
regular expression \.[Pp][Dd][Ff] also can be used
Thanks
Thanks for this tip, works perfectly in everything but safari.. looking for a solution to that problem now..
PS. Drupal rocks!
Useful for download folders
I run the IT direction for several companies and occasionally need to offer files for download without going through the hassle of creating stub pages, or explaining (again!) to users that email isn't the best place to attach a 10MB file.
I stopped by to mention that the code above also works quite well within Apache VirtualHosts directives. Simply include the block above inside the appropriate virtual host, such as "download.mydomain.com" and you can serve your files via HTTP, leaving the rest of your subdomains (such as "www") to serve the content you have time to write.
One quite valuable side-effect is that this also allows administrators to split download functions to another server (read: faster connection) when demand surpasses capacity...without rewriting everything you've done to provide downloadable content.
To wit, thank you; you saved me enough research time that I could stop to...hopefully :)...add value to your writeup. Cheers!
Better Method
First of all FilesMatch does not work in older versions of Apache.
Secondly, it is far easier to alter the mime types. Just add this to your .htaccess file:
AddType application/octet-stream .pdf
Post new comment