我遇到了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
,但这没有帮助。
答案 0 :(得分:4)
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: I'm sending you a file!
标题一样有用。
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
答案 1 :(得分:3)
某些版本的IE似乎需要
header( 'Expires: 0' );
header( 'Cache-Control: must-revalidate, pre-check=0, post-check=0' );
太认真了,并且在将下载的内容传递给插件之前将其删除以显示它。
删除这两个,你应该没事。
在使用PDF时,请确保您没有使用任何服务器端GZIP压缩,因为某些版本的Acrobat似乎很难解决这个问题。
我知道我在这里很模糊,但上面的提示基于我使用Web应用程序提供的实际经验,该应用程序提供包含条形码的动态构建的PDF。我不知道哪些版本受到影响,我只知道使用上面的两个“技巧”使得支持电话消失了:p
答案 2 :(得分:1)
一年前我遇到了完全相同的问题,经过大量的谷歌搜索和研究,我的标题(来自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文件。但那应该不重要。
答案 3 :(得分:1)
我感谢你们在这篇文章上花的时间。我尝试了几种组合,最后得到了我的symfony项目。在这里,我发布解决方案,以防任何人遇到同样的问题:
public function download(sfResponse $response) {
$response->clearHttpHeaders();
$response->setHttpHeader('Pragma: public', true);
$response->addCacheControlHttpHeader("Cache-control","private");
$response->setContentType('application/octet-stream', true);
$response->setHttpHeader('Content-Length', filesize(sfConfig::get('sf_web_dir') . sfConfig::get('app_paths_docPdf') . $this->getFilename()), true);
$response->setHttpHeader("Content-Disposition", "attachment; filename=\"". $this->getFilename() ."\"");
$response->setHttpHeader('Content-Transfer-Encoding', 'binary', true);
$response->setHttpHeader("Content-Description","File Transfer");
$response->sendHttpHeaders();
$response->setContent(readfile(sfConfig::get('sf_web_dir') . sfConfig::get('app_paths_docPdf') . $this->getFilename()));
return sfView::NONE;
}
在IE6,IE7,Chrome,Firefox中,这对我来说很合适。
希望这会对某人有所帮助。
答案 4 :(得分:0)
正如pilif已经提到过的,请务必关闭服务器端的gzip压缩。对我来说,这会导致PDF文件(以及其他类型)出现问题,并且因为Internet Explorer和FireFox下的.zip文件也可能不那么模糊。
据我所知,压缩页脚的最后一位会被剥离(至少是FireFox)导致格式损坏。
在PHP中,您可以使用以下代码:
ini_set("zlib.output_compression",0);
答案 5 :(得分: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过滤器)。没有任何区别(在我测试过的四个浏览器中没有任何问题)。 另外,这也适用于其他文件类型。
答案 6 :(得分:0)
您可以将服务器无法读取的其他参数添加到它可能有用的网址中。
http://www.mycom.com/services/pdf?action=blahblah&filename=pdf0001.pdf
我遇到过哪种情况,即更有可能读取网址末尾的文件名而不是任何标题
答案 7 :(得分:0)
我遇到了类似的问题,但可能并不完全相关。我的问题是IE6似乎在文件名中有特殊字符(特别是斜杠)的问题。删除这些解决了这个问题。
答案 8 :(得分:0)
如果您使用的是SSL:
确保您不包含任何缓存控件(或Pragma)标头。 IE6中存在一个错误,如果使用缓存控制头,它将阻止用户下载文件。他们会收到一条错误消息。
我把头发拉了两天,所以希望这个消息有助于某人。
答案 9 :(得分:0)
只需切换到此内容类型即可使用,同时确保Pragma设置为不等于“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