联调时出现mediatype的报错,属于Content-Type配错了,回来补充下这方面的知识点
对比 请求报文、响应报文
Accept属于请求头, Content-Type属于实体头
- Accept属于 请求首部字段,只有HTTP请求有。
- Content-Type属于 实体首部字段,HTTP请求和响应 都拥有该字段。
- 注意:get请求和post请求默认 Content-Type 是 application/json,但是 GET 请求不会带有请求体(request body),它是字符串拼接的
?id=123
这种,因此 Content-Type 的设置对 GET 请求并不产生影响。
- 注意:get请求和post请求默认 Content-Type 是 application/json,但是 GET 请求不会带有请求体(request body),它是字符串拼接的
Accept代表发送端(客户端)希望接受的数据类型
比如:
1 | // 代表客户端希望接受的数据类型是json类型 |
Content-Type代表发送端(客户端/服务器)发送的实体数据的数据类型
比如:
1 | // 代表发送端发送的数据格式是json |
二者结合在请求头中
二者合起来在请求头中,代表希望接受的数据类型是json格式,本次请求发送的数据的数据格式是json:
1 | Accept:"application/json"; |
常见的媒体类型(MediaType)
Accept
和Content-Type
的常见值(即 的媒体类型(MediaType)):- text/html:HTML格式
- text/plain:纯文本格式
- text/xml: XML格式
- image/gif:gif图片格式
- image/jpeg:jpg图片格式
- image/png:png图片格式
- application/xhtml+xml:XHTML格式
- application/xml: XML数据格式
- application/atom+xml:Atom XML聚合格式
- application/json:JSON数据格式
- application/pdf:pdf格式
- application/msword: Word文档格式
- application/octet-stream: 二进制流数据(如常见的文件下载)
- application/x-www-form-urlencoded:
<form encType="">
中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格- 式) - multipart/form-data: 需要在表单中进行文件上传时,就需要使用该格式
"Accept: */*"
:表示客户端(通常是浏览器)能够接受所有类型的响应。这通常是用在浏览器向服务器请求页面时使用的,告诉服务器客户端能够处理任何返回的内容类型。- 例如,在请求中包含
"Accept: */*"
头字段,表示客户端能够处理的响应类型可以是 HTML、XML、JSON 等。
- 例如,在请求中包含
使用场景
处理调用接口时的报错
- 当报mediatype错时,一般是前端调用接口时发出的请求头中
Content-Type
与后端写接口时规定的希望接收到的数据格式不符,更改请求头中Content-Type
即可- 比如:前端发出的
Content-Type
为application/json
JSON数据格式,但是后端要application/x-www-form-urlencoded
,自然就报错了 - h12-header中可查看前端发出的请求头
- 注意:后端希望接收到的数据格式 和 响应头的
Content-Type
没关系,并不是要请求头中Content-Type
与响应头的Content-Type
一致就不会报错。明确,响应头Content-Type
是说明后端会 发送 的数据格式,而这里的问题是前端 发送 的数据格式(Content-Type
)和后端希望 接收 到的数据格式不符。
- 比如:前端发出的
axios配置请求头content-type
- Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。
- 设置方法、配置的优先级 可参考文档的例子,非常详细
- axios 发送post请求时默认是直接把 json 放到请求体中提交到后端的,axios默认的请求头
content-type
类型是application/json;charset=utf-8
- axios可自动转换 JSON 数据,从后端获取的JSON数据并不需要通过JSON方法去转换为JS对象,直接就可使用JS对象。
content-type
的三种常见数据格式:1
2
3
4
5
6
7
8
9// 1 默认的格式请求体中的数据会以json字符串的形式发送到后端
'Content-Type: application/json ' // 默认
// 2 请求体中的数据会以普通表单形式(键值对)发送到后端
'Content-Type: application/x-www-form-urlencoded'
// 3 它会将请求体的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件
// 常见前端页面上传个人图像,然后点击保存发送后端修改原始数据
'Content-Type: multipart/form-data'
设置方法
- 我最常用到的是post请求的’application/x-www-form-urlencoded’和’application/json’,这里用设置为表单类型为例
- 毕竟json格式是默认的,也不需要另外设置
- get请求没有请求体,也不需要设置content-type,get的参数会将查询字符串设置为
?id=123&type=user
这种,请求体是空的
- 最常用的是调用接口的时候进行设置:
1
2
3
4
5
6
7
8
9
10
11
12
13import Qs from 'qs' // qs库是 axios 里面包含的,不需要再下载
let params= {"name": "ll","age": "18"} // 传参
// ...async函数中...
const res = await axios({
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
method: 'post',
url: url, // 调用的接口
data: Qs.stringify(params) // 为啥有的application/x-www-form-urlencoded需要qs转换可看下方解释,注意:如果是Content-Type是json格式,data接收的就是对象而不是这样的字符串
}) - 改变全局 axios 默认值:
1
2
3axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
// 或
axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded'; - 给自定义实例设置默认值:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// 方法1:创建实例时配置默认值
const DkAxios = axios.create({
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
});
// 方法2:创建实例后修改默认值
DkAxios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';
// 方法1和2实际使用方法...async函数中...
const res1 = await DkAxios({
method: 'post',
url: url, // 调用的接口
data: Qs.stringify(params)
})
// 方法3:调用实例时设置
const res2 = await DkAxios({
method: 'post',
url: url, // 调用的接口
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: Qs.stringify(params)
})
使用qs.stringify(data)
的场景和原因
- 当使用 Axios 发送 POST 请求时,默认使用
Content-Type: application/json
头部,并将请求数据转换为 JSON 字符串- Axios 使用了默认的请求拦截器(request interceptor),在发送请求之前会自动对请求数据进行转换
- 这适用于大多数情况,特别是当使用 JSON 作为数据格式进行数据交换时
- 当
headers
中的Content-Type
被设置为application/x-www-form-urlencoded
时,需要将data
(请求数据)转换成URLSearchParams
对象(即表单数据格式),也就是key1=value1&key2=value2
这样的形式,然后再发送HTTP请求。这就需要使用qs.stringify(data)
方法进行手动序列化,然后再将序列化后的数据作为请求体data
发送- 注意:手动序列化后的数据应该是一个字符串,而不是对象。因此在请求时,需要将序列化后的数据直接作为请求体传递给Axios,而不是将其包装在一个对象中。(上面例子中可看到)