43

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

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

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

4

3 回答 3

37

绝对使用 Content-Length。由此产生的服务器利用率几乎不存在,并且对您的用户的好处将很大。

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

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

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

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

于 2010-03-10T18:19:08.860 回答
12

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

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

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

于 2010-03-10T18:24:58.287 回答
10

内容长度

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

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

传输编码

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

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

传输编码更好地利用了持久的chunkedTCP 连接,HTTP 1.1 默认假定为真。

内容编码

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

请注意,Content-Length等于 之后的主体长度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用于你的压缩。

分块与存储和转发

于 2017-12-11T12:27:42.780 回答