内容描述类响应头
Content-Type / Content-Length / Content-Encoding / Content-Disposition / Content-Language 等描述响应体类型、大小、编码和处置方式的响应头。
[!info] related notes
- 所属 MOC: http-and-frontend-networking-moc
- 总览: http-response-headers
- 上位主题: http
- 关联概念: 协商缓存(ETag 也是内容描述的一种)
- 下载专题: large-file-download-range-request
内容描述类响应头
一句话定义
内容描述类响应头告诉客户端:响应体是什么类型、多大、用了什么压缩、应该直接展示还是下载。
Content-Type
告诉客户端:响应体是什么类型。浏览器根据它决定如何处理响应。
常见值与浏览器行为
Content-Type | 浏览器行为 |
|---|---|
text/html; charset=utf-8 | 当 HTML 解析并渲染 |
application/json; charset=utf-8 | 作为 JSON 数据 |
text/css | 作为 CSS |
application/javascript | 作为 JS |
image/png | 作为图片 |
application/pdf | 作为 PDF |
application/octet-stream | 通用二进制,常配合下载 |
charset 的重要性
Content-Type: text/html; charset=utf-8
Content-Type: application/json; charset=utf-8
对于现代 Web,charset=utf-8 很重要,避免中文乱码。省略 charset 可能导致浏览器用错误编码解析。
常见错误
后端返回 JSON 但写成:
Content-Type: text/html
结果:前端 response.json() 解析失败,安全策略(CSP、X-Content-Type-Options)可能失效,甚至触发 MIME sniffing 风险。
正确:
Content-Type: application/json; charset=utf-8
与 X-Content-Type-Options 的关系
当设置了 X-Content-Type-Options: nosniff 时,浏览器不再猜测类型,严格按 Content-Type 处理。如果 Content-Type 写错,浏览器会直接拒绝执行。详见 → x-content-type-options
Content-Length
告诉客户端响应体的字节长度(不是字符数)。
Content-Length: 12345
注意事项
| 场景 | Content-Length |
|---|---|
| 普通响应 | 常见,框架自动设置 |
| gzip/br 压缩后 | 应该是压缩后字节数 |
| 流式响应(chunked) | 通常不设置 |
| HTTP/1.1 Transfer-Encoding: chunked | 不设置 |
手动设置错误的后果
浏览器等待更多数据 → 响应被截断 → 代理报错 → 前端偶发网络错误
多数框架会自动处理,不建议业务代码手写 Content-Length。
Content-Encoding
告诉客户端:响应体用了什么内容编码压缩。
Content-Encoding: gzip
Content-Encoding: br
Content-Encoding: zstd
典型协商流程
# 浏览器请求
Accept-Encoding: gzip, deflate, br, zstd
# 服务器响应
Content-Encoding: br
三个容易混淆的头
| 头 | 含义 |
|---|---|
Content-Type | 内容原本是什么格式:HTML、JSON、图片 |
Content-Encoding | 内容传输前被怎么压缩:gzip、br、zstd |
Transfer-Encoding | HTTP/1.1 传输分块机制(如 chunked),和业务内容类型不是一回事 |
例如:
Content-Type: application/json
Content-Encoding: gzip
意思是:这是 JSON,但传输时被 gzip 压缩了。两者不冲突,是两层。
与缓存的关系
如果同一 URL 对不同客户端返回不同压缩版本,必须设置:
Vary: Accept-Encoding
否则 CDN 可能把 gzip 版本发给只支持 br 的客户端。详见 → Vary 与缓存键
Content-Language
告诉客户端内容的语言。不是翻译功能,只是声明”这个响应内容是什么语言”。
Content-Language: zh-CN
Content-Language: en-US
Content-Language: ko-KR
用途:多语言页面、SEO、屏幕阅读器、内容协商。
Content-Disposition
控制浏览器是直接展示还是下载。
两种模式
| 值 | 行为 |
|---|---|
inline | 尽量在浏览器内打开 |
attachment | 触发下载 |
文件名指定
Content-Disposition: attachment; filename="report.pdf"
Content-Disposition: attachment; filename*=UTF-8''%E6%8A%A5%E5%91%8A.pdf
| 写法 | 说明 |
|---|---|
filename="report.pdf" | ASCII 文件名 |
filename*=UTF-8''编码后的文件名 | 支持 UTF-8 文件名,中文推荐用这个 |
中文文件名建议用 filename*,否则不同浏览器可能乱码。
最小场景
PDF 预览:
Content-Type: application/pdf
Content-Disposition: inline; filename="report.pdf"
文件下载:
Content-Type: application/octet-stream
Content-Disposition: attachment; filename*=UTF-8''report.xlsx
Content-Length: 123456
Content-Location
表示响应内容对应的具体资源位置。
Content-Location: /users/123/profile
它不等于重定向(重定向用 Location)。实际工程里用得少,更多出现在内容协商和 REST 资源表示场景。
边界与易混淆点
- Content-Encoding 不是 Content-Type 的一部分:它们是两层,Type 说格式,Encoding 说压缩。
- Content-Length 是字节数不是字符数:中文 UTF-8 占 3 字节,emoji 占 4 字节。
- Content-Disposition 的 inline vs attachment:
inline只是”建议”,浏览器可能仍然下载(如未知 MIME 类型)。 - 不要手动写 Content-Length:框架自动处理更安全,手动写错会导致响应截断或代理报错。