ThingyMaJig

Thingy Ma Jig is the blog of Nicholas Thompson and contains any useful tips, sites and general blog-stuff which are considered interesting or handy!

Connect

LinkedIn GitHub

Topics

announcement 25 apache 3 Apple 1 bash 8 code 7 cool 30 Days Out 8 Dark Basic Pro 4 design 12 doctor who 1 Drupal 74 E4600 1 EOS 400D 3 firefox 2 Flickr 3 free 21 games 5 geek 38 git 2 GreaseMonkey 1 hardware 7 Homebrew 1 How to 37 humour 5 iphone 1 javascript 1 jquery 1 K800i 6 k850i 4 lighttpd 3 linux 33 mac 9 miscellaneous 4 mobile phone 9 music 4 mysql 8 n73 1 n95 1 New Relic 1 Ogre3D 1 OS X 2 performance 3 photos 10 programming 40 Quicksilver 1 review 19 security 3 SEO 6 software 12 svn 2 technology 4 tip 7 tips 10 tv 3 video 3 vim 7 webdev 2 websites 33 wii 1 windows 1 YADS 10

Force a PDF to download

Posted on 06 August 2007 in
software programming linux cool apache

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!