chunked_transfer_encoding的核心是服务器按需生成并逐块发送响应体,无需预知总长度,适用于流式响应等场景;其结构为每块以十六进制长度+CRLF+数据+CRLF组成,终块为0+CRLF+CRLF。

利用 chunked_transfer_encoding 控制分块传输,核心在于让服务器按需生成、逐块发送响应体,不依赖总长度预知,适用于流式响应、动态内容或大文件传输场景。关键不是“开启”,而是正确构造 chunked 编码格式并维持传输逻辑。
理解 chunked 编码的基本结构
Chunked 传输将响应体切分为若干块(chunk),每块以十六进制长度开头,后跟 CRLF、实际数据、再跟 CRLF。最后一块长度为 0,表示结束。例如:
0a\r\nHelloWorld\r\n
00\r\n
说明:第一块长度是 0a(十进制 10),数据为 HelloWorld;末块 00 表示终止。中间不能遗漏任何 CRLF,也不能混入额外空格或换行。
在服务端手动构造 chunked 响应
若使用底层 HTTP 接口(如 Python 的 socket、Go 的 net/http.ResponseWriter 或 Node.js 的 res.write()),需显式设置 header 并分次写入:
- 响应头中必须包含
Transfer-Encoding: chunked,且不能同时设置Content-Length - 每次写入一块前,先写入长度(十六进制字符串 + CRLF),再写数据 + CRLF
- 结束时写入
0\r\n\r\n(注意两个 CRLF) - 确保所有写入操作不缓冲——禁用自动 flush,必要时主动调用
flush()或end()
避免常见陷阱
Chunked 传输容易因细节出错而被客户端截断或报错:
- 编码长度错误:十六进制长度必须严格等于后续字节数(不是字符数,注意 UTF-8 多字节)
-
换行符不统一:必须用
\r\n,不可用\n替代 - 提前关闭连接:未发送终块就断开,会导致客户端等待超时
- 与压缩冲突:若启用 gzip,需先压缩再分块,或让中间件(如 Nginx)处理压缩,否则编码会错乱
借助框架的流式响应能力
多数现代框架已封装 chunked 逻辑,只需启用流式写入:
- Express(Node.js):调用
res.write(chunk)后不立即end(),最后res.end()自动补终块 - Flask(Python):返回生成器函数,Flask 自动设为 chunked;也可用
Response(stream, direct_passthrough=True) - Spring WebFlux(Java):返回
Flux<string></string>或StreamingResponseBody,底层自动 chunked
此时无需手算长度或拼接 CRLF,但需确保响应体无静态 Content-Length,且中间代理(如 Nginx)未禁用或缓存流式响应。

















