繁体   English   中英

内容长度标头与分块编码

[英]Content-Length header versus chunked encoding

我正在尝试权衡设置Content-Length HTTP 标头与使用分块编码从我的服务器返回 [可能] 大文件的利弊。 需要使用持久连接来符合 HTTP 1.1 规范。 我看到Content-Length标头的优点是:

  • 下载对话框可以显示准确的进度条
  • 客户预先知道文件可能/可能不会太大而无法摄取

缺点是必须在返回对象之前计算大小,这并不总是实用并且可能会增加服务器/数据库的利用率。 分块编码的缺点是在每个块和下载进度条之前添加块大小的开销很小。 有什么想法吗? 我可能没有想到的这两种方法的任何其他 HTTP 考虑因素?

绝对使用内容长度。 这样做的服务器利用率几乎不存在,对您的用户的好处将是巨大的。

对于动态内容,添加压缩响应支持 ( gzip ) 也非常简单。 这需要输出缓冲,从而为您提供内容长度。 (不适用于文件下载或已经压缩的内容(声音、图像))。

还考虑添加对部分内容/字节范围服务的支持 - 即重新启动下载的功能。 有关字节范围示例,请参见此处(该示例使用 PHP,但适用于任何语言)。 提供部分内容时需要 Content-Length。

当然,这些都不是灵丹妙药:对于流媒体来说,使用输出缓冲或响应大小是没有意义的; 对于大文件,输出缓冲没有意义,但 Content-Length 和字节服务很有意义(重新启动失败的下载是可能的)。

就我个人而言,只要我知道,我就会提供 Content-Length; 对于文件下载,检查文件大小在资源方面无关紧要。 结果:用户有一个确定的进度条(由于 gzip,动态页面下载速度更快)。

如果事先知道内容长度,那么我当然更喜欢它而不是分块发送。 如果在本地磁盘文件系统或数据库中有静态文件的方法,那么任何自尊的编程语言和 RDBMS 都提供了预先获取内容长度的方法。 你应该好好利用它。

另一方面,如果内容长度事先真的不可预测(例如,当您的意图是将多个文件压缩在一起并将其作为一个发送时),那么将其分块发送可能比将其缓存在服务器内存中或写入本地磁盘要快首先是文件系统。 但这确实会对用户体验产生负面影响,因为下载进度未知。 不耐烦的人然后可以中止下载并继续前进。

事先知道内容长度的另一个好处是能够恢复下载。 我在你的帖子历史中看到你的主要编程语言是 Java; 您可以在此处找到包含更多技术背景信息的文章和执行此操作的 Java Servlet 示例。

内容长度

Content-Length标头确定请求/响应正文的字节长度。 如果您忽略指定Content-Length标头,HTTP 服务器将隐式添加Transfer-Encoding: chunked标头。 Content-LengthTransfer-Encoding标头不应一起使用。 接收者将不知道主体的长度是多少,也无法估计下载完成时间。 如果您确实添加了Content-Length标头,请确保它以字节为单位匹配整个正文,如果不正确,则接收者的行为未定义。

Content-Length标头不允许流式传输,但它对于您希望支持部分内容服务的大型二进制文件很有用。 这基本上意味着可恢复下载、暂停下载、部分下载和多宿主下载。 这需要使用名为Range的附加标头。 这种技术称为字节服务

传输编码

Transfer-Encoding: chunked的使用允许在单个请求或响应中进行流式传输。 这意味着数据以分块的方式传输,并且不会影响内容的表示。

正式的 HTTP 客户端旨在发​​送带有TE标头字段的请求,该字段指定客户端愿意接受的传输编码类型。 这并不总是发送,但是大多数服务器假设客户端可以处理chunked编码。

chunked传输编码更好地利用了持久性 TCP 连接,默认情况下 HTTP 1.1 假定为真。

内容编码

也可以压缩分块或非分块数据。 这实际上是通过Content-Encoding标头完成的。

请注意, Content-Length等于Content-Encoding之后的Content-Encoding长度。 这意味着如果您对响应进行了 gzip 压缩,那么长度计算将在压缩之后进行。 如果您想计算长度,您将需要能够将整个主体加载到内存中(除非您在其他地方有该信息)。

使用分块编码进行流式传输时,压缩算法还必须支持在线处理。 幸运的是,gzip 支持流压缩。 我相信内容首先被压缩,然后被切成块。 这样,块被接收,然后解压缩以获取真实内容。 如果是相反的方式,您将获得压缩流,然后解压缩将为我们提供块。 这没有意义。

典型的压缩流响应可能具有以下标头:

Content-Type: text/html
Content-Encoding: gzip
Transfer-Encoding: chunked

从语义上讲, Content-Encoding的使用表示“端到端”编码方案,这意味着只有最终客户端或最终服务器应该对内容进行解码。 中间的代理不应该解码内容。

如果要允许中间的代理对内容进行解码,则要使用的正确标头实际上是Transfer-Encoding标头。 如果 HTTP 请求拥有TE: gzip chunked标头,则使用Transfer-Encoding: gzip chunked进行响应是合法的。

然而,这很少得到支持。 因此,您现在应该只使用Content-Encoding进行压缩。

分块 vs 存储转发

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM