代码之家  ›  专栏  ›  技术社区  ›  Gandalf

内容长度头与分块编码

  •  30
  • Gandalf  · 技术社区  · 14 年前

    我在权衡设置 Content-Length 与使用分块编码从我的服务器返回[可能]大文件相比,http头。一个或另一个需要使用持久连接来符合http 1.1规范。我看到了 内容长度 标题为:

    • 下载对话框可以显示准确的进度条
    • 客户机预先知道文件是否太大而无法接收

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

    3 回复  |  直到 7 年前
        1
  •  31
  •   Piskvor left the building Rohit Kumar    14 年前

    一定要使用内容长度。由此产生的服务器利用率几乎是不存在的,对用户的好处将是巨大的。

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

    还可以考虑添加对 部分内容 /字节范围服务——也就是重新启动下载的能力。 See here for a byte-range example (该示例使用php,但适用于任何语言)。提供部分内容时需要内容长度。

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

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

        2
  •  11
  •   BalusC    14 年前

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

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

    预先知道内容长度的另一个好处是能够恢复下载。我在您的邮政历史中看到,您的主要编程语言是Java;您可以找到 here 具有更多技术背景信息的文章和一个Java servlet示例。

        3
  •  4
  •   Dhairya Lakhera    7 年前

    内容长度

    这个 Content-Length 头决定请求/响应正文的字节长度。如果忽略指定 内容长度 头,http服务器将隐式地添加 Transfer-Encoding: chunked 标题。这个 内容长度 Transfer-Encoding 标题不应一起使用。接收者将不知道主体的长度,并且无法估计下载完成时间。如果你真的添加了 内容长度 头,确保它与整个正文的字节数匹配,如果不正确,则接收器的行为未定义。

    这个 内容长度 头文件不允许流式处理,但它对于要支持部分内容服务的大型二进制文件非常有用。这基本上意味着可恢复的下载、暂停的下载、部分下载和多宿主下载。这需要使用名为 Range . 这种技术叫做 Byte serving .

    传输编码

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

    正式地说,http客户端是用来发送带有 TE 头字段,指定客户端愿意接受的传输编码类型。这并不总是发送的,但是大多数服务器假定客户端可以处理 chunked 编码。

    这个 分块的 传输编码更好地利用了持久的TCP连接,而HTTP 1.1默认情况下假定该连接为真。

    内容编码

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

    请注意 内容长度 等于 内容编码 . 这意味着如果您已经gzip响应,那么长度计算将在压缩之后进行。如果要计算长度,则需要能够将整个主体加载到内存中(除非在其他地方有该信息)。

    当使用分块编码流时,压缩算法还必须支持在线处理。值得庆幸的是,gzip支持流压缩。我相信内容首先被压缩,然后被分割成块。这样,块被接收,然后被解压以获得真正的内容。如果它是相反的方式,你会得到压缩流,然后解压缩会给我们块。这没道理。

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

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

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

    如果要允许中间的代理解码内容,正确的头实际上是 传输编码 标题。如果http请求拥有 TE: gzip chunked 头,那么用 Transfer-Encoding: gzip chunked .

    然而,这很少得到支持。所以你应该只使用 内容编码 为了你现在的压力。

    Chunked vs Store & Forward

    推荐文章