← 返回题目列表

常见请求 Content-Type 有哪些?JSON、FormData 和表单提交怎么选择?

高频 中等 第 2 / 26 题 更新于 2026/07/29
Content-TypeFormDataJSON前端网络

简化版

常见请求体类型包括 application/jsonapplication/x-www-form-urlencodedmultipart/form-data 和文本/二进制流。普通接口常用 JSON,传统表单可用 urlencoded,文件上传用 FormData 对应 multipart;使用 FormData 时不要手动写 Content-Type,浏览器会自动带上 boundary。

详细版

JSON 请求:

fetch('/api/user', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Tom' }),
})

文件上传:

const form = new FormData()
form.append('avatar', file)
form.append('name', 'Tom')
fetch('/api/upload', { method: 'POST', body: form })

面试重点是说清编码格式、服务端解析方式、是否触发 CORS 预检、是否适合文件上传,以及浏览器如何自动处理 multipart boundary。

完整版教学

一、Content-Type 是请求体说明书

服务端收到请求体时,需要知道这串字节应该按什么格式解析。Content-Type 就是请求体的媒体类型说明,前端设置错了,服务端可能读不到参数或解析失败。

类型格式常见场景
application/jsonJSON 字符串现代 API
application/x-www-form-urlencodeda=1&b=2传统表单
multipart/form-data多段边界分隔文件上传
text/plain纯文本简单文本上报

记忆钩子:JSON 管结构,urlencoded 管简单键值,multipart 管文件和混合字段。

二、JSON 请求的特点

fetch('/api/order', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ id: 1, items: [2, 3] }),
})

JSON 表达嵌套对象和数组很自然,前后端接口最常用。代价是跨域时 application/json 不属于简单请求的简单 Content-Type,通常会触发 OPTIONS 预检。

假设请求从 app.example.com 发到 api.example.com,POST JSON 往往会先出现一次 OPTIONS,再出现真实 POST。这个现象不是多发了业务请求,而是浏览器安全检查。

三、urlencoded 的特点

const body = new URLSearchParams({ name: 'Tom', age: '18' })

fetch('/api/form', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },
  body,
})

urlencoded 适合简单键值,浏览器传统表单默认就常用它。它不擅长表达复杂嵌套结构,不同后端对数组和对象的解析约定也可能不同,例如 ids=1&ids=2ids[]=1&ids[]=2

四、FormData 和 multipart

const form = new FormData()
form.append('file', file)
form.append('desc', 'avatar')

fetch('/upload', {
  method: 'POST',
  body: form,
})

multipart/form-data 会把每个字段分成一段,文件字段可以带文件名和类型。浏览器会自动生成类似 boundary=----WebKitFormBoundary... 的分隔符。

不要手动设置:

headers: { 'Content-Type': 'multipart/form-data' } // 常见错误

如果手动写了但没有 boundary,服务端无法知道各段如何分隔,上传解析就可能失败。

五、CORS 简单请求与预检

跨域请求是否预检,和方法、头部、Content-Type 都有关。简单 Content-Type 只包括有限几种,例如 application/x-www-form-urlencodedmultipart/form-datatext/plain

请求是否常触发预检
POST + JSON
POST + urlencoded通常否
POST + multipart + 自定义头可能是
带 Authorization 头

为了避免预检而把所有接口改成 text/plain 通常不是好设计。预检是安全机制,优化要从缓存 Access-Control-Max-Age、减少不必要自定义头、合并请求等方向考虑。

六、服务端解析和安全边界

前端发什么 Content-Type,服务端就要启用对应解析器。JSON 解析器、表单解析器、文件上传中间件处理方式不同,大小限制也不同。

请求 -> 根据 Content-Type 选择 parser -> 得到 body/files -> 业务校验

文件上传尤其要限制大小、类型和数量。前端可以做格式提示,但不能替代服务端校验;攻击者可以直接构造请求绕过前端限制。

七、常见误区与追问

  • 误区:所有 POST 都应该用 JSON。 文件上传和传统表单有更合适的编码方式。
  • 误区:FormData 要手动设置 Content-Type。 浏览器会自动设置 multipart boundary,手动设置反而容易错。
  • 误区:预检请求是接口重复调用。 OPTIONS 是浏览器的跨域许可检查,不是业务提交。
  • 追问:为什么 JSON 跨域常有预检? application/json 不属于简单 Content-Type。
  • 追问:urlencoded 能传复杂对象吗? 可以约定编码,但不同后端解析规则不统一。
  • 追问:前端限制文件类型安全吗? 只能改善体验,服务端必须重新校验。

八、加强记忆

请求体类型按“结构、表单、文件”记:结构化数据用 JSON,简单表单用 urlencoded,文件和混合字段用 FormData/multipart。答题时一定补上两个边界:FormData 不手写 Content-Type,JSON 跨域常触发预检。Content-Type 不是随便填的字符串,而是前后端解析协议。