【问题标题】:PDF Generation Results in ERR_INVALID_RESPONSE in Chrome在 Chrome 中生成 ERR_INVALID_RESPONSE 的 PDF 生成结果
【发布时间】:2016-04-08 13:04:24
【问题描述】:

在浏览器中以编程方式(通过 PHP)生成 PDF 时,呈现的 PDF 在 Firefox 和 Safari 中都可以正常显示,但 Chrome 会返回 ERR_INVALID_RESPONSE。它是一个有效的 PDF - 一旦从工作浏览器保存,就可以使用 Adob​​e Reader/Preview 在本地打开,一旦从其他浏览器保存 PDF,它甚至可以在 Chrome 中打开。

PDF 文件正在通过file_get_contents() 读取,被赋予当前时间戳,然后传递给浏览器。解决方法是将文件保存到临时位置并重定向用户(至少对于 Chrome),但这并不理想。

我已经研究过了,只能找到bug reports dating from 2008

我知道这是一个标题错误。生成 PDF 后,将以下标头发送到浏览器(在 FF、Safari 和 IE 中再次正常工作):

    header('Content-type:application/pdf');
    header("HTTP/1.1 200 OK");

我也尝试在 Stack Overflow 上搜索后添加以下标题,但无济于事:

    header("Content-Transfer-Encoding: binary");
    header('Accept-Ranges: bytes');

是否缺少 Chrome 所需的标头?有没有人有让动态生成的 PDF 在 Chrome 中显示的经验?

编辑:我的一个更突出的问题是什么可能导致它在 Chrome 本地运行良好,但不能在服务器环境中运行。

【问题讨论】:

  • 您是否尝试过将配置更改为附件? header('Content-Disposition: attachment;; filename="YourFileName"');
  • @HNA 我有 - 无论是否使用附件,Chrome 都会出现同样的错误。有两个按钮:“保存”,它会抛出 header('Content-Disposition: attachment;');,以便自动下载文件(这在 Chrome、FF 和 Safari 中本地运行,并且在 Safari 和 Firefox 中非本地运行)。另一个按钮“查看”仅显示 PDF 而不会自动下载。目前两者都不能在非本地实例中的 Chrome 中工作。
  • 您发送header('Content-Length: ' . filesize($yourfile)); 吗?
  • @maxhb 是的。以下标头随请求一起发送:header('Content-Type: application/pdf');header('Content-Disposition: inline; filename="' . $filename . '"');header('Expires: 0');header('Cache-Control: must-revalidate, post-check=0, pre-check=0');header('Pragma: public');header('Content-Length: ' . $length);
  • Chrome 首先需要 Status 200 Header。这有效: header( $_SERVER["SERVER_PROTOCOL"] . ' 200 OK' ); header('内容类型:应用程序/pdf'); header('Content-Disposition: inline; filename="' . $filename . '"' ); header('内容传输编码:二进制'); header('接受范围:字节');

标签: php google-chrome pdf


【解决方案1】:

在我的情况下,我必须将这两个参数添加到标题中,因为 wordpress 正在发送 404 代码,因为它无法识别我的 php 函数的 url:

header("Content-type: application/pdf",true,200);

answer on wordpress.stackexchange 中所述。

这会强制标头替换(第二个参数true)由 wordpress 生成的 404 状态代码,因为它无法识别自定义 url,并设置 200 OK(第三个参数200)。

所以就这样结束了:

$pdf_name = "test.pdf";
$pdf_file = "/absolute/path/to/my/pdfs/on/my/server/{$pdf_name}";
header('Content-type: application/pdf',true,200);
header("Content-Disposition: attachment; filename={$pdf_name}");
header('Cache-Control: public');
readfile($pdf_file);
exit();

【讨论】:

    【解决方案2】:

    试试这个

    <?php
    $filename = 'Physical Path to PDf file.pdf';
    $content = file_get_contents($filename);
    
    header("Content-type:application/pdf");
    
    // It will be called downloaded.pdf
    header("Content-Disposition:inline;filename='".basename($filename)."'");   
    header('Content-Length: '.strlen( $content ));
    
    // The PDF source is in original.pdf
    readfile($filename);
    ?>
    
    <html>
    <body>
    ...
    ...
    ...
    

    确保在 PHP 脚本输出之前调用了上面的头代码 发送到浏览器。

    【讨论】:

    • 感谢您的建议。我已经尝试并重新尝试了这些标题,但没有运气。我在对原始问题的评论中发布了附加标题的完整列表。还要注意,我们实际上并没有将文件“读取”到浏览器,而是读取 PDF,修改它,然后将新创建的文件作为立即下载附件或在浏览器的 PDF 查看器中提供(它没有保存在此过程中的任何时候到磁盘)。
    【解决方案3】:

    我要感谢大家的回答。

    事实证明这与标题无关。在尝试以各种方式更改/删除标头(检测编码、尝试使用和不使用 content-length 等)之后,我们决定深入挖掘 httpd 日志,看看 Chrome 是否有任何不同的解决方案。

    事实证明,我们服务器上的 mod_sec 将请求(出于某种原因仅来自 Chrome)标记为尝试文件注入攻击,并返回 403 禁止响应。 Chrome 将其显示为 ERR_INVALID_RESPONSE 而不是 403。

    请求中存在 CDN 的主机名(我们在端点进行了充分检查以确保文件确实是允许的资源),而是在服务器上构建 URL。

    【讨论】:

    • 你是怎么解决的?我遇到了同样的问题。
    • 我需要知道该问题的解决方案,我遇到了同样的问题。它能够显示图像但不会显示 PDF 引用 ERR_INVALID_RESPNSE 这实际上是 403 错误。
    • @netrox 解决方案包含在答案中。由于我们的 CDN 的 url (AmazonS3) 出现在查询中,我们的被抛出。我们从 URL 中删除了它,然后在端点重新添加了它。
    • 你是什么意思而不是在服务器上构建 url @AndrewKlatzke
    • @Pascal 我们一直在查询中发送整个 CDN url。我们不是直接在请求(&key={endpointUrl}/resource)上发送它,而是只发送资源句柄,在请求到达后找出端点(CDN url),连接两者并使用该版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-01
    • 2023-04-04
    • 2020-04-11
    • 2016-01-07
    • 1970-01-01
    • 2016-01-10
    • 1970-01-01
    相关资源
    最近更新 更多