Force PDFs to download in IIS 7+

Recently I received a request from a client where they wished to have all PDFs download directly as attachments instead of opening up on an installed viewer on the visitors machine. I instantly started racking my brain as to a quick and simple way to accomplish this.

I remembered reading there was a way to specify how a file downloads directly in an anchor tag in HTML5 (here) but being HTML5 isn’t 100% yet I decided that wasn’t the best way. Being the site was built on the ASP.NET MVC Framework I instantly started going through the quick exercise of creating a controller action that would receive a file name and serve it out through a file result. Knowing this method is wrought with security concerns I locked down the directory where files were pulled from so no matter what was requested the code would only ever look in a single folder on the server.

This method wasn’t ideal but it was quick and it was done. I then start the task of updating all links to point to my newly created action instead of the direct linking to a PDF. After the second change I was already in pain and knew that there must be a better way.

Then I remembered we had the URL Rewriting Module installed for IIS which I had previously used for redirecting all HTTP requests to HTTPS, maybe I could use that for outbound requests as well. A quick Google search later returned this beauty:

<rewrite>
<outboundRules>
<rule name="Forcing Download for PDFs" preCondition="IsPDF">
<match serverVariable="RESPONSE_Content-Disposition" pattern=".*" />
<conditions>
<add input="{REQUEST_FILENAME}" pattern="(.*)\([^/]+).pdf$" />
</conditions>
<action type="Rewrite" value="attachment; filename={C:2}.pdf" />
</rule>
<preConditions>
<preCondition name="IsPDF">
<add input="{REQUEST_FILENAME}" pattern=".pdf$" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>

When added to the sites web.config file in between the <system.webServer> tags, IIS 7 (requires URL Rewriter Module) will modify all outbound requests that have: a Content-Disposition header and match a requested file of (.*)\([^/]+).pdf$ and append the appropriate header tag attachment; filename={C:2}.pdf to get the file to download instead of opening up directly in an installed viewer.