Content-Length标头与分块编码

时间:2010-03-10 17:58:12

标签: performance http chunked-encoding content-length

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

  • 下载对话框可以显示准确的进度条
  • 如果文件可能/可能不会太大而无法摄取
  • ,则客户端会提前知道

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

3 个答案:

答案 0 :(得分:31)

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

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

还要考虑添加对部分内容 /字节范围服务的支持 - 即重启下载的功能。 See here for a byte-range example(示例在PHP中,但适用于任何语言)。在提供部分内容时,您需要Content-Length。

当然,那些不是银子弹:对于流媒体,使用输出缓冲或响应大小毫无意义;对于大文件,输出缓冲没有意义,但内容长度和字节服务很有意义(重启失败的下载是可能的)。

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

答案 1 :(得分:11)

如果预先知道内容长度,那么我肯定更愿意在上面发送内容。如果本地磁盘文件系统或数据库中存在静态文件,那么任何自尊的编程语言和RDBMS都会提供预先获取内容长度的方法。你应该利用它。

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

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

答案 2 :(得分:5)

内容 - 长度

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

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

<强>传送-编码

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

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

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

内容-编码

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

请注意Content-Length等于Content-Encoding之后的身体长度。这意味着如果你已经压缩了你的响应,那么长度计算会在压缩后发生。如果要计算长度,则需要能够将整个主体加载到内存中(除非您在其他地方有这些信息)。

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

典型的压缩流响应可能包含以下标题:

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

在语义上,Content-Encoding的使用表示&#34;端到端&#34;编码方案,这意味着只有最终客户端或最终服务器才能解码内容。中间的代理不会对内容进行解码。

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

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

Chunked vs Store & Forward