transfer-encoding chunked , Transfer-Encoding 的作用

本文深入解析HTTP1.1协议中的Transfer-Encoding头,阐述其在数据传输中的作用,特别是在chunked编码方式下如何解决未知长度数据的传输问题。同时对比Content-Encoding,解释两者区别及与Content-Length的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过HTTP传送数据时,有些时候并不能事先确定body的长度,因此无法得到Content-Length的值, 就不能在header中指定Content-Length了,造成的最直接的影响就是:接收方无法通过Content-Length得到报文体的长度, 那怎么判断发送方发送完毕了呢?HTTP 1.1协议在header中引入了Transfer-Encoding,当其值为chunked时, 表明采用chunked编码方式来进行报文体的传输

HTTP 1.1中有两个实体头(Entity-Header)直接与编码相关,分别为Content-Encoding和Transfer-Encoding.
先说Content-Encoding, 该头表示实体已经采用了的编码方式.Content-Encoding是请求URL对应实体(Entity)本身的一部分.比如请求URL为http://host/image.png.gz时,可能会得到的Content-Encoding为gzip.Content-Encoding的值是不区分大小写的,目前HTTP1.1标准中已包括的有gzip/compress/deflate/identity等.


与Content-Encoding头对应,HTTP请求中包含了一个Accept-Encoding头,该头用来说明用户代理(User-Agent,一般也就是浏览器)能接受哪些类型的编码. 如果HTTP请求中不存在该头,服务器可以认为用户代理能接受任何编码类型.

接下来重点描述Transfer-Encoding, 该头表示为了达到安全传输或者数据压缩等目的而对实体进行的编码. Transfer-Encoding与Content-Encoding的不同之处在于:

 

  1. Transfer-Encoding只是在传输过程中才有的,并非请求URL对应实体的本身特性.
  2. Transfer-Encoding是一个"跳到跳"头,而Content-Encoding是"端到端"头.

该头的用途举例如,请求URL为http://host/abc.txt,服务器发送数据时认为该文件可用gzip方式压缩以节省带宽,接收端看到Transfer-Encoding为gzip首先进行解码然后才能得到请求实体.
此外多个编码可能同时对同一实体使用,所以Transfer-Encoding头中编码顺序相当重要,它代表了解码的顺序过程.同样,Transfer-Encoding的值也是不区分大小写的,目前HTTP1.1标准中已包括的有gzip/compress/deflate/identity/chunked等.
Transfer-Encoding中有一类特定编码:chunked编码.该编码将实体分块传送并逐块标明长度,直到长度为0块表示传输结束, 这在实体长度未知时特别有用(比如由数据库动态产生的数据). HTTP1.1标准规定,只要使用了Transfer-Encoding的地方就必须使用chunked编码,并且chunked必须为最后一层编码.任何HTTP 1.1应用都必须能处理chunked编码.
与Transfer-Encoding对应的请求头为TE,它主要表示请求发起者愿意接收的Transfer-Encoding类型. 如果TE为空或者不存在,则表示唯一能接受的类型为chunked.
其他与Transfer-Encoding相关的头还包括Trailer,它与chunked编码相关,就不细述了.

顾名思义,Content-Length表示传输的实体长度,以字节为单位(在请求方法为HEAD时表示会要发送的长度,但并不实际发送.).Content-Length受Transfer-Encoding影响很大,只要Transfer-Encoding不为identity,则实际传输长度由编码中的chunked决定,Content-Length即使存在也被忽略.

关于HTTP Message Body的长度
在HTTP中有消息体(Message body)和实体(Entity body)之分,简单说来在没有Transfer-Encoding作用时,消息体就是实体,而应用了Transfer-Encoding后,消息体就是编码后的实体,如下:

    Message body = Transfer-Encoding encode(Entity body)
如何确定消息体的长度? HTTP 1.1标准给出了如下方法(按照优先级依次排列):
    1, 响应状态(Response Status)为1xx/204/304或者请求方法为HEAD时,消息体长度为0.
    2, 如果使用了非"identity"的Transfer-Encoding编码方式,则消息体长度由"chunked"编码决定,除非该消息以连接关闭为结束.
    3, 如果存在"Content-Length"实体头,则消息长度为该数值.
    3, 如果消息使用关闭连接方式代表消息体结束,则长度由关闭前收到的长度决定. 该条对HTTP Request包含的消息体不适用.


 

<think>我们正在处理一个关于HTTP协议中Transfer-Encoding:chunked的问题,特别是Java环境下的含义和使用场景。根据提供的引用,我们可以总结以下关键点:引用[3]和[4]详细解释了Transfer-Encoding:chunked作用-它用于在服务器无法预先确定响应体大小时(例如动态生成内容),将响应分成多个块(chunk)传输。-使用这种编码方式时,响应头中不会包含Content-Length,而是用Transfer-Encoding:chunked代替。-每个块包含一个十六进制表示的块大小,后跟数据,最后以0大小的块结束。引用[2]提到在Java(特别是Spring)中:-当使用contentLength()方法设置内容长度时,如果文件太大或无法预知大小,Spring会自动切换到分块传输。-SpringBoot和Servlet容器通常会自动处理Transfer-Encoding和Content-Length,但在某些情况下需要手动干预。用户的问题集中在Java中,因此我们需要结合Java的Servlet和Spring框架来说明。回答结构:1.解释Transfer-Encoding:chunked的基本含义。2.说明在Java(Servlet/Spring)中的工作原理和自动处理机制。3.列举使用场景。4.可能的手动控制方法(如果需要)。同时,根据系统指令,我们需要生成相关问题。</think>### Java 中 Transfer-Encoding: chunked 的含义与使用场景 #### 1. **核心含义** `Transfer-Encoding: chunked` 是 HTTP/1.1 协议定义的**分块传输编码机制**,用于处理服务器无法预先确定响应体完整大小的场景。其核心特点包括: - **分块结构**:响应体被拆分为多个"块"(chunk),每个块包含十六进制表示的块大小 + 实际数据(例如:`5\r\nHello\r\n`)。 - **结束标识**:以 `0\r\n\r\n` 标记传输结束。 - **无 Content-Length**:响应头中**不会**包含 `Content-Length` 字段,因为总长度在传输前未知[^3][^4]。 #### 2. **在 Java 中的作用** Java 应用(如 Servlet 容器、Spring Boot)自动启用分块传输的场景: - **动态内容生成**:当服务器无法预知响应大小时(如实时数据流、数据库查询结果),自动切换为分块传输。 ```java // Spring Boot 示例:返回大型动态数据 @GetMapping("/stream") public ResponseEntity<StreamingResponseBody> streamData() { return ResponseEntity.ok() .header("Transfer-Encoding", "chunked") // 通常自动添加 .body(outputStream -> { // 边生成数据边写入(无需预知总大小) while (hasData()) { outputStream.write(generateChunk()); } }); } ``` - **性能优化**:避免服务器为计算完整响应大小而等待,减少内存占用和延迟[^2][^4]。 #### 3. **典型使用场景** - **实时数据流**:日志推送、股票行情、实时监控(如 WebSocket 替代方案)。 - **大文件下载**:文件边读取边传输,无需预加载到内存(如视频流)。 - **API 长响应**:生成耗时较长的 API 响应(如复杂报表),客户端可逐步接收数据[^3][^4]。 #### 4. **Java 中的手动控制** 虽然 Servlet 容器(Tomcat/Jetty)和 Spring Boot 通常自动处理分块传输,但可通过以下方式干预: - **强制禁用分块**:明确设置 `Content-Length`(仅当数据大小已知时)。 ```java response.setContentLength(data.length); // 禁用分块传输 ``` - **自定义块大小**:在 `StreamingResponseBody` 中控制每次写入的数据量[^2]。 > **关键区别**: > - `Content-Encoding`(如 gzip)**压缩数据**以减少体积; > - `Transfer-Encoding: chunked` **改变传输格式**以支持流式传输,二者可同时使用[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值