views:

1804

answers:

12

I've come across a rather interesing (and frustrating) problem with IE6. We are serving up some server generated pdfs and then simply setting headers in PHP to force a browser download of the file. Works fine and all, except in IE6 but only if the windows user account is set to standard user (ie. not administrator).

Since this is for a corporate environment, of course all their accounts are setup this way. Weird thing is, that in the download dialog, the Content-Type is not recognized:

header( 'Pragma: public' );
header( 'Expires: 0' );
header( 'Cache-Control: must-revalidate, pre-check=0, post-check=0' );
header( 'Cache-Control: public' );
header( 'Content-Description: File Transfer' );
header( 'Content-Type: application/pdf' );
header( 'Content-Disposition: attachment; filename="xxx.pdf"' );
header( 'Content-Transfer-Encoding: binary' );
echo $content;
exit;

I also tried writing the file content to a temporary file first so I could also set the Content-Length in the header but that didn't help.

A: 

Can you verify that all the users have permissions to download files, and/or to run adobe reader?

Unkwntech
A: 

Yeah, they definitely do. They did all the testing in Firefox (so this never cropped up during development) and everything worked fine on the same machine. I tested this on VmWare too where i quickly setup a new user which resulted in the same error.
I'm close to setting up a case for IE users where I write a file and redirect them to the pdf file instead of letting them download. Opening pdf files directly does not seem to be affected by this..

Polygraf
+1  A: 

I have had the exact same problem about a year ago, and after much googling and research, my headers (from Java code) look for IE6 & PDFs like this:

    response.setHeader("Content-Type", "application/pdf "; name=" + file.getName());
    response.setContentType("application/pdf");
    response.setHeader("Last-Modified", getHeaderDate(file.getFile());
    response.setHeader("Content-Length", file.getLength());

Drop everything else.

There is apparently something a bit whacky with IE6, caching, forced downloading and plug-ins. I hope this works for you...a small difference for me is that the request initially comes from a Flash swf file. But that should not matter.

Stu Thompson
A: 

Stu, thanks for the answer but unfortunately that didn't do the trick in this case, same error as before. (I actually only added the cache headers, etc. because that worked well for IE users in another project, before that I'd only set the content-type and force download).

I talked to our admin here and he actually thinks it might have something to do with IE6 not properly implementing some system security policy. IE7 on the same system actually works.

Polygraf
+3  A: 

some versions of IE seem to take

header( 'Expires: 0' );
header( 'Cache-Control: must-revalidate, pre-check=0, post-check=0' );

way too seriously and remove the downloaded content before it's passed to the plugin to display it.

Remove these two and you should be fine.

And make sure you are not using any server-side GZIP compression when working with PDFs because some versions of Acrobat seem to struggle with this.

I know I'm vague here, but above tips are based on real-world experience I got using a web application serving dynamically built PDFs containing barcodes. I don't know what versions are affected, I only know that using the two "tricks" above made the support calls go away :p

pilif
A: 

As pilif already mentions, make sure to turn off the server-side gzip compression. For me this has caused problems with PDF files (among other types) and for maybe-not-so-obscure reasons also with .zip files both under Internet Explorer and FireFox.

As far as I could tell, the last bit of the zip footer would get stripped (at least by FireFox) causing a corrupted format.

In PHP you can use the following code:

ini_set("zlib.output_compression",0);
Twan
A: 

The following bit of Java code works for me (tested on Firefox 2 and 3, IE 6 and 7):

response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
response.setContentType(getServletContext().getMimeType(file.getName()));
response.setContentLength(file.length());

No other headers were necessary at all. Also, I tested this code both with gzip compression on and off (using a separate servlet filter that does the compression). Doesn't make any difference (works without any problem in the four browsers I tested it on). Plus, this works for other filetypes as well.

Tom De Leu
A: 

You can add an additional parameter that the server won't read to the url it might help too.

http://www.mycom.com/services/pdf?action=blahblah&filename=pdf0001.pdf

I have run into cases where ie will be more likely to read the filename on the end of the url than any of the headers

Steve g
+3  A: 

These headers are bogus!

Content-Transfer-Encoding: binary

This header is copied from e-mail headers. It doesn't apply to HTTP simply because HTTP doesn't have any other mode of transfer than binary. Setting it makes as much sense as setting X-Bits-Per-Byte: 8.

Cache-control: pre-check=0, post-check=0

These non-standard values define when IE should check whether cached content is still fresh. 0 is the default, so setting it to 0 is waste of time. These directives apply only to cacheable content, and Expires:0 and must-revalidate hint that you wanted to make it non-cacheable.

Content-Description: File Transfer

This is another e-mail copycat. By design this header doesn't affect download in any way. It's just informative free-form text. It's technically as useful as X-Hi-Mom: I'm sending you a file! header.

header( 'Cache-Control: must-revalidate, pre-check=0, post-check=0' );
header( 'Cache-Control: public' );

In PHP second line completely overwrites the first one. You seem to be stabbing in the dark.

What really makes a difference

Content-Disposition: attachment

You don't have to insert filename there (you can use mod_rewrite or index.php/fakefilename.doc trick – it gives much better support for special characters and works in browsers that ignore the optional Content-Disposition header).

In IE it makes difference whether file is in cache or not ("Open" doens't work for non-cacheable files), and whether user has plug-in that claims to support type of file that IE detects.

To disable cache you only need Cache-control:no-cache (without 20 extra fake headers), and to make file cacheable you don't have to send anything.

NB: PHP has horrible misfeature called session.cache_limiter which hopelessly screws up HTTP headers unlesss you set it to none.

ini_set('session.cache_limiter','none'); // tell PHP to stop screwing up HTTP
porneL
On Kubuntu, the default for Apache/php5 sets `session.cache_limiter = nocache`.
Dave Jarvis
A: 

I had a similar problem, but it might not be exactly related. My issue was that IE6 seems to have a problem with special characters (specifically slashes) in the file name. Removing these fixed the issue.

paulwhit
A: 

If you are using SSL:

Make sure you do not include any cache control (or Pragma) headers. There is a bug in IE6 which will prevent users from downloading files if cache control headers are used. They will get an error message.

I pulled my hair out over this for 2 days, so hopefully this message helps someone.

A.J. Brown
A: 

simply switch to this content type and it will work, also be sure Pragma ist set to something NOT equal "no-cache"

header( 'Content-type: application/octet-stream'); # force download, no matter what mimetype
header( 'Content-Transfer-Encoding: binary' ); # is always ok, also for plain text
zolex