4

我在 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在标题中设置,但这没有帮助。

4

10 回答 10

4

这些标题是假的!

Content-Transfer-Encoding: binary

此标头是从电子邮件标头复制而来。它不适用于 HTTP,因为 HTTP 除了二进制之外没有任何其他传输模式。设置它和设置一样有意义X-Bits-Per-Byte: 8

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

这些非标准值定义了 IE 何时应该检查缓存的内容是否仍然新鲜。0是默认值,所以设置它0是浪费时间。这些指令仅适用于可缓存内容,Expires:0must-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_rewriteindex.php/fakefilename.doc欺骗 - 它为特殊字符提供了更好的支持,并且在忽略可选 Content-Disposition标题的浏览器中工作)。

在 IE 中,文件是否在缓存中(“打开”不适用于不可缓存的文件)以及用户是否拥有声称支持 IE 检测到的文件类型的插件会有所不同。

要禁用缓存,您只需要Cache-control:no-cache(没有 20 个额外的假标头),并且要使文件可缓存,您无需发送任何内容。

注意:PHP 有一个可怕的错误功能session.cache_limiter,除非您将其设置为none.

ini_set('session.cache_limiter','none'); // tell PHP to stop screwing up HTTP
于 2009-04-08T18:14:30.653 回答
3

某些版本的 IE 似乎需要

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

太认真了,并在下载的内容传递给插件以显示之前将其删除。

删除这两个,你应该没问题。

并确保在处理 PDF 时没有使用任何服务器端 GZIP 压缩,因为某些版本的 Acrobat 似乎很难解决这个问题。

我知道我在这里含糊其辞,但以上提示是基于我使用 Web 应用程序获得的实际经验,该应用程序提供动态构建的包含条形码的 PDF。我不知道哪些版本受到影响,我只知道使用上面的两个“技巧”使支持电话消失了:p

于 2008-09-08T08:38:20.623 回答
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 文件。但这应该没关系。

于 2008-09-08T08:23:41.297 回答
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 中效果很好。

希望这会对某人有所帮助。

于 2011-04-20T15:12:00.240 回答
0

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);
于 2008-09-16T13:48:22.930 回答
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 过滤器进行压缩)。没有任何区别(在我测试过的四个浏览器中没有任何问题)。另外,这也适用于其他文件类型。

于 2008-09-25T17:25:11.717 回答
0

您可以将服务器不会读取的附加参数添加到它可能也有帮助的 url。

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

我遇到过这样的情况,即 ie 更有可能读取 url 末尾的文件名而不是任何标题

于 2008-09-25T17:31:01.470 回答
0

我有一个类似的问题,但它可能不完全相关。我的问题是 IE6 似乎在文件名中存在特殊字符(特别是斜杠)的问题。删除这些解决了这个问题。

于 2009-07-28T18:49:12.923 回答
0

如果您使用 SSL:

确保不包含任何缓存控制(或 Pragma)标头。IE6 中存在一个错误,如果使用缓存控制标头,将阻止用户下载文件。他们将收到一条错误消息。

我为此拉了两天的头发,所以希望这条消息对某人有所帮助。

于 2010-02-03T15:28:43.637 回答
0

只需切换到此内容类型,它就会工作,还要确保 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
于 2010-09-21T09:35:37.560 回答