【问题标题】:Content-Length header is correct but downloading tools are stopping when headers+body = content-lengthContent-Length 标头正确,但当 headers+body = content-length 时下载工具停止
【发布时间】:2021-09-15 04:07:00
【问题描述】:

我遇到了一个奇怪的问题,不知道接下来的调试步骤。我希望社区可以提出一些想法。

我正在使用以下堆栈:

PHP 7.2.34-21+ubuntu16.04.1+deb.sury.org+1 (fpm-fcgi) (built: May  1 2021 11:52:36)
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.34-21+ubuntu16.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies
Server version: Apache/2.4.39 (Ubuntu)
Wordpress 4.9.16

在 AWS 服务上。显然,由于框架存在一些开销,但我可以将代码简化为以下内容:

// Framework stuff + file handling logic
$data = 'Imagine this is a 1000-byte binary message (pdf).';

// Headers, 335 bytes large
header('date: Sat, 03 Jul 2021 05:06:41 GMT');
header('server: Apache/2.4');
header('expires: Wed, 11 Jan 1984 05:00:00 GMT');
header('cache-control: no-cache, must-revalidate, max-age=0');
header('content-disposition: inline; filename=window-sticker.pdf');
header('strict-transport-security: max-age=1209600;');
header('content-length: 1000'); // Actually use strlen($data); for this
header('x-ua-compatible: IE=edge');
header('cache-control: public');
header('content-type: application/pdf');

echo $data;

exit();

现在这是踢球者。这在许多其他站点上运行良好,据我所知,使用相同的 apache sites-enabled 配置和类似的 .htaccess 文件。但它可能仍然是服务器/网络/等。类型错误,所以我可能会遗漏一些东西。

我有这个网站,但是,此代码以下列方式中断:

  • 不强制执行content-length 的工具可以完美地下载/显示此内容(例如chrome)。
  • 跟踪content-length 的工具会失败或发出通知(safari、curl)。卷曲给了我:
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7ff13c008200)
> GET /redacted/path/to/controller?p=abcdef HTTP/2
> Host: www.redacted-somesite.com
> User-Agent: curl/7.64.1
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
  0     0    0     0    0     0      0      0 --:--:--  0:00:05 --:--:--     0< HTTP/2 200
< date: Sun, 04 Jul 2021 17:36:24 GMT
< server: Apache/2.4
< expires: Wed, 11 Jan 1984 05:00:00 GMT
< cache-control: no-cache, must-revalidate, max-age=0
< content-disposition: inline; filename=window-sticker.pdf
< strict-transport-security: max-age=1209600;
< content-length: 1000
< x-ua-compatible: IE=edge
< cache-control: public
< content-type: application/pdf
<
* HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)
* stopped the pause stream!
  0  1000    0     0    0     0      0      0 --:--:--  0:00:05 --:--:--     0
* Connection #0 to host www.redacted-somesite.com left intact
curl: (92) HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)
* Closing connection 0

我检查过的东西:

  • 内容长度IS设置正确,正文与该标头中设置的大小相同。
  • 数据 IS 正在输出,因为 chrome 等工具可以获取完整文件
  • 删除 content-length 标头可以在所有工具中使用。

现在,我不确定为什么事情会失败。我目前的理论是,不知何故,对于这个站点,一些静默错误可能会在标头发出之前写入缓冲区。但是当我用十六进制工具检查从服务器发送的二进制数据时,它是完全匹配的。所以我很茫然。也许有一些压缩层在搞我?

任何想法都会很棒。

谢谢!

【问题讨论】:

  • 这能回答你的问题吗? HTTP Headers for File Downloads
  • @Top-Master 不是真的。我确实想在浏览器中显示它,并且我已经包含了 content-typecontent-disposition 标题。
  • 您正在使用的确切 Apache 版本是什么,包括 fpm 模块以及正在使用的确切 php-fpm 版本(php 版本)是什么[对于您遇到问题的服务器]?这看起来像是软件不兼容/配置错误。 conent-length 应该定义明确。我假设分块传输没有起作用(你清楚地写了标题大小被考虑在内,是的,它不应该)。使用 wireshark 或类似工具在传输层进行验证。
  • 我总是在发送标头之后和发送有效负载之前使用 ob_clean() 清除输出缓冲区,它往往会消除很多像这样的奇怪问题。这有点像货物崇拜,但在深入兔子洞之前先试一试。
  • 你能在命令行上试试 curl 吗?它有很好的-v 开关,因此它显示请求和响应标头(与-i 结合),管道进入输出文件,然后它显示确切的字节,并且写入的字节也可以通过输出文件的大小看到.

标签: php wordpress apache


【解决方案1】:

更新以匹配 OP 的最新编辑:

您提到的工具似乎不再使用 HTTP v1.1 协议, 有关 cURL 的“HTTP/2 流 0 未完全关闭”错误,请参阅 similar answer


旧答案:

内容长度应与文件大小完全相同, 但如果是的话,也许你缺少一些其他的标题,比如:

Content-Transfer-Encoding: binary

如果所有标头都在那里,请检查最大 PHP 执行。

另见 example of download with resume support 另一个帖子。

【讨论】:

  • 我可以确认长度是正确的。我仔细检查了+这个确切的代码在其他网站上运行良好。此错误仅特定于一种设置。我还尝试添加 content-transfer-encoding 标头,但它不能解决问题。
  • 如果所有标题都存在,请检查最大 PHP 执行(并且可能添加恢复支持,但在添加“Accept-Ranges: bytes”标题之前不应该是必需的)。
  • Content-Length 独立于 Content-Transfer-Encoding: binary。还有 Accept-Ranges: 字节(它要么需要实现,要么需要前端服务器处理)。另外我想知道这是否会遇到 PHP 最大执行,OP 不会提到它。也许检查一下日志?
  • 这不是最大执行问题,我可以通过简单地使用 chrome 来使其正常工作,并且日志中没有迹象表明存在违规行为。
  • 已编辑:希望我提到的链接有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-12
  • 2021-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多