HTTP 表单提交 vs. 文件上传
· 13 min read

Conceptual Difference
首先要明确:这两种都是 HTTP POST 请求中 Content-Type 头的取值,用于规定客户端(浏览器/前端)如何将表单数据编码后发送给服务端,服务端再对应解码获取数据。
1. 先分别理解两种格式
(1)application/x-www-form-urlencoded
这是 HTML 表单的默认编码格式(如果不手动指定 enctype,表单提交就用这种格式)。
核心特点:
- 会将表单中的键值对数据进行 URL 编码(也叫百分号编码):
- 键和值之间用
=连接,键值对之间用&分隔; - 非 ASCII 字符、特殊字符(空格、
&、=等)会被转换成%XX格式(比如空格转+或%20,中文中转%E4%B8%AD) 。
- 键和值之间用
- 所有数据拼接成一个单一的字符串,放在请求体中发送,没有边界分隔符。
- 数据明文传输(请求体可直接查看编码后的字符串),体积紧凑但不支持二进制数据。
示例(表单数据:用户名=张三,密码=123&456)
编码后的请求体内容:
username=%E5%BC%A0%E4%B8%89&password=123%26456
(2)multipart/form-data
这是一种用于传输复杂数据(尤其是二进制文件)的编码格式,需要手动指定表单的 enctype="multipart/form-data" 才能使用。
核心特点:
- 不会对数据进行 URL 编码,而是将表单数据拆分成多个“部分(part)”,每个部分对应一个表单字段(键值对或文件)。
- 每个部分之间用**唯一的边界分隔符(boundary)**分隔(boundary 由客户端随机生成,放在
Content-Type头中告知服务端,比如Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW)。 - 每个部分都有自己的小头部(如
Content-Disposition),描述该部分的字段名、文件名(文件字段)、内容类型(二进制文件)等信息。 - 支持传输文本数据和二进制数据(图片、视频、文档等),是文件上传的唯一可行格式,但数据体积相对较大(有边界分隔符等额外开销)。
示例(表单数据:用户名=张三,文件=test.txt)
请求体内容(简化版):
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="username"
张三
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
这是test.txt的文件内容
------WebKitFormBoundary7MA4YWxkTrZu0gW--
2. 核心差异对比
为了更直观,用表格总结两者的关键区别:
| 对比维度 | application/x-www-form-urlencoded | multipart/form-data |
|---|---|---|
| 默认与否 | 是(HTML 表单默认编码) | 否(需手动指定 enctype) |
| 数据编码方式 | 进行 URL 编码(特殊字符转 %XX) | 不进行 URL 编码,用 boundary 分隔各部分 |
| 支持的数据类型 | 仅支持文本数据(键值对文本) | 支持文本数据 + 二进制数据(文件等) |
| 适用场景 | 普通表单提交(无文件上传,仅简单键值对) | 包含文件上传的表单提交(核心场景) |