I have the following code that returns a PDF file in my web application:
string path = "help.pdf";
byte[] data = File.ReadAllBytes(path);
Response.Clear();
Response.ClearHeaders();
Response.AddHeader("Content-Length", data.Length.ToString());
Response.AddHeader("Content-Type", "application/pdf");
Response.AddHeader("Content-Disposition", "attachment; filename=help.pdf");
Response.OutputStream.Write(data, 0, data.Length);
Response.End();
When I call the handler of this code in any browser (Chrome, IE or Firefox), I get a "Save as..." dialog with the name of the page (index.aspx
) rather than the name provided in the code (help.pdf
).
I also checked the following:
application/pdf
with application/octet-stream
: problem is gone (but we are using third party export tools that I can't modify in this way, so this is not a solution)I checked the HTTP response header with all browsers. It looks like this:
Cache-Control:private
Content-Disposition:attachment
Content-Length:89407
Content-Type:application/pdf
Date:Thu, 07 May 2015 08:43:12 GMT
Server:Microsoft-IIS/7.5
X-Powered-By:ASP.NET
X-UA-Compatible:IE=edge,chrome=1
As you can see the filename parameter is removed from the Content-Disposition field. So the behaviour of the browsers is correct. The web server (IIS) seems to tinker around with the header.
I found somebody with the same problem here. But the problem was never solved. Any ideas?
The problem was that because of an IIS 7.5 issue someone added the following lines to the web.config
file of the application:
<outboundRules>
<rule name="Force pdfs to download" preCondition="only match pdfs">
<match serverVariable="RESPONSE_Content_Disposition" pattern="(.*)" />
<action type="Rewrite" value="attachment" />
</rule>
<preConditions>
<preCondition name="only match pdfs">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^application/pdf" />
</preCondition>
</preConditions>
</outboundRules>