IE6中的文件下载
我遇到了一个与IE6相当有趣(令人沮丧)的问题。我们提供了一些服务器生成的pdf文件,然后只需在PHP中设置标头即可强制浏览器下载该文件。除了在IE6中运行外,其他所有功能都正常运行,但前提是Windows用户帐户设置为标准用户(即非管理员)。
由于这是在公司环境中使用的,因此当然可以使用这种方式来设置其所有帐户。奇怪的是,在下载对话框中,无法识别Content-Type:
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;
我还尝试先将文件内容写入临时文件,这样我也可以在标头中设置" Content-Length",但这无济于事。
解决方案
回答
大约一年前,我遇到了完全相同的问题,经过大量的搜索和研究,我的标头(来自Java代码)查找IE6和PDF,如下所示:
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());
放下其他所有东西。
IE6,缓存,强制下载和插件显然有些不明智。我希望这对我们有用...对我来说,一个小区别是请求最初来自Flash swf文件。但这无关紧要。
回答
某些版本的IE似乎需要
header( 'Expires: 0' ); header( 'Cache-Control: must-revalidate, pre-check=0, post-check=0' );
过于认真,请先删除下载的内容,然后再将其传递给插件以显示它。
删除这两个,就可以了。
并确保在使用PDF时不使用任何服务器端GZIP压缩,因为某些版本的Acrobat似乎为此感到困扰。
我知道我在这里含糊不清,但以上技巧是基于我使用网络应用程序提供的动态经验而得出的,该应用程序可动态构建包含条形码的PDF。我不知道受影响的版本,我只知道使用上面的两个"技巧"使支持电话消失了:p
回答
正如pilif已经提到的,请确保关闭服务器端gzip压缩。对我来说,这引起了PDF文件(以及其他类型)的问题,并且由于可能(不是很晦涩的原因)也导致了Internet Explorer和FireFox下的.zip文件出现问题。
据我所知,zip页脚的最后一位将被剥离(至少被FireFox剥离),从而导致格式损坏。
在PHP中,我们可以使用以下代码:
ini_set("zlib.output_compression",0);
回答
以下Java代码对我有用(在Firefox 2和3,IE 6和7上测试):
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\""); response.setContentType(getServletContext().getMimeType(file.getName())); response.setContentLength(file.length());
根本不需要其他头。
另外,我在打开和关闭gzip压缩的情况下都测试了此代码(使用单独的servlet过滤器进行压缩)。没什么区别(在我测试过的四种浏览器中都可以正常工作)。
另外,这也适用于其他文件类型。
回答
我们可以添加一个服务器将不会读取的添加参数,这可能也有帮助。
http://www.mycom.com/services/pdf?action=blahblah&filename=pdf0001.pdf
我遇到过这样的情况,即,与任何标题相比,ie更有可能读取url末尾的文件名
回答
这些标题是伪造的!
Content-Transfer-Encoding: binary
此标题是从电子邮件标题复制的。它不仅仅适用于HTTP,因为HTTP除了二进制以外没有其他传输方式。设置它与设置" X-Bits-Per-Byte:8"一样有意义。
Cache-control: pre-check=0, post-check=0
这些非标准值定义IE应该何时检查缓存的内容是否仍然新鲜。默认值为0,因此将其设置为0是浪费时间。这些指令仅适用于可缓存的内容,而Expires:0
和must-revalidate
暗示我们要使其成为不可缓存的内容。
Content-Description: File Transfer
这是另一个电子邮件模仿者。按照设计,此标头不会以任何方式影响下载。这只是内容丰富的自由格式文本。从技术上讲,它与" X-Hi-Mom:我要向我们发送文件!"标头一样有用。
header( 'Cache-Control: must-revalidate, pre-check=0, post-check=0' ); header( 'Cache-Control: public' );
在PHP中,第二行完全覆盖第一行。你似乎在黑暗中刺伤。
真正有什么不同
Content-Disposition: attachment
我们不必在其中插入文件名(可以使用mod_rewrite
或者index.php / fakefilename.doc
技巧,它为特殊字符提供了更好的支持,并且可以在忽略可选的Content-Disposition
标头的浏览器中使用) 。
在IE中,文件是否在缓存中("不可打开"不适用于不可缓存的文件)以及用户是否具有声称支持IE检测到的文件类型的插件都将有所不同。
要禁用缓存,我们只需要Cache-control:no-cache
(没有20个额外的假头),并且使文件可缓存,我们无需发送任何内容。
注意:PHP具有可怕的功能错误,称为" session.cache_limiter",除非将其设置为" none",否则它毫无希望地破坏了HTTP标头。
ini_set('session.cache_limiter','none'); // tell PHP to stop screwing up HTTP
回答
我有一个类似的问题,但可能不完全相关。我的问题是IE6似乎在文件名中存在特殊字符(特别是斜杠)的问题。删除这些可解决问题。
回答
如果我们使用的是SSL:
确保我们不包括任何缓存控件(或者Pragma)标头。 IE6中存在一个错误,如果使用了缓存控制标头,它将阻止用户下载文件。他们将收到错误消息。
我将头发拉了两天,因此希望此消息对某人有所帮助。
回答
只需切换到该内容类型即可使用,并且还要确保将Pragma ist设置为不等于" 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