前后端联调编码格式探究
前后端联调的时候经常要约定数据交互的编码格式;这里我们所说的编码格式即是————HTTP请求头部的属性Content-Type。
更多解释还请看MDN:Content-Type
content-type 作为文件的编码类型有很多种,在前后端的交互中,请求头与返回(响应)头都有;
这些头里面的 content-type 可以由前端、后端程序员控制;
这里我主要想了解一下前端发送请求时的请求头的 content-type:
- application/json
- application/x-www-form-urlencoded
- multipart/form-data
其他常见的页面资源类型:text/html, text/plain, text/css, text/javascript, image/jpeg, image/png, image/gif
application/json
当我们使用这种格式的时候,浏览器会将这种数据格式放在 Request Payload 这个载体中。
-
格式案例
{"name":"","psd":""}
-
Chrome浏览器的 Request Payload 中可以看到我们所传输的数据,形式案例如下:
-
axios传输注意,传输这种格式的时候只要将 header 的配置写对,基本就不会有太大问题,案例代码:
this.$api.post('/prefix/postBody', params, { headers: { 'Content-Type': 'application/json' } }).then(res => { console.log('res', res) })
application/x-www-form-urlencoded
当我们使用这种格式的时候,浏览器会将这种数据格式放在 Form Data 这个载体中。
- 格式案例
test=1&a=2&b=3
- Chrome浏览器的 Form Data 中可以看到我们所传输的数据,形式案例如下:
(这里与我们上方格式不同是因为Chrome浏览器为了方便我们观测,作了解析)
- axios传输注意,传输这种格式的时候除了将 header 的配置写对,传输数据类型的格式也要写好(注意了,不能直接使用 JSON.stringify 来进行序列化;因为它的stringify并不能达到将obj对象数据转化为"test=1&a=2&b=3"的类型,通常我们使用qs库的stringify函数):
const params = qs.stringify({ test: 1, a: 2, b: 3 }) this.$api.post('/prefix/postBody', params, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).then(res => { console.log('res', res) })
multipart/form-data
- 格式案例:
参照网上的博客,它可能是多种数据合并起来的,所以并非有统一的格式;我们可以规定字符(boundary)来确定他们的分隔符号是什么。
参考微软小哥的博客 - Chrome浏览器的 Form Data 中可以看到我们所传输的数据,形式案例如下:
- axios案例:
const formData = new FormData() formData.append('name', 'chp') formData.append('age', '23') formData.append('sex', 'male') this.$api.post('/prefix/multi', formData, { headers: { 'Content-Type': 'multipart/form-data' } }).then(res => { console.log('res', res) })
最常见的情境是:在写邮件时,向邮件后添加附件,附件通常使用表单添加,也就是用multipart/form-data格式上传到服务器。
The encoding type application/x-www-form-urlencoded is inefficient for sending large quantities of binary data or text containing non-ASCII characters. Thus, a new media type,multipart/form-data, is proposed as a way of efficiently sending thevalues associated with a filled-out form from client to server.
问:为什么要新增一个类型,而不使用旧有的application/x-www-form-urlencoded?
答:因为此类型不适合用于传输大型二进制数据或者包含非ASCII字符的数据。平常我们使用这个类型都是把表单数据使用url编码后传送给后端,二进制文件当然没办法一起编码进去了。所以multipart/form-data就诞生了,专门用于有效的传输文件。
- application/x-www-form-urlencoded 对于发送大量二进制数据或包含非ASCII字符的文本效率低下。
- multipart/form-data 应该用于提交包含文件,非ASCII数据和二进制数据的表单。
总结图
前端发送的请求头类型 | 在Chrome的Network哪里进行观测 | 传输的数据形式 |
---|---|---|
application/json | Request Payload | |
application/x-www-form-urlencoded | Form Data | test=1&a=2&b=3 |
multipart/form-data | Form Data | 和application/x-www-form-urlencoded一样的键值对 或者 文件等二进制数据 |
相关知识:比较其中的异同点
enctype 默认"application/x-www-form-urlencoded"对表单数据进行编码,数据以键值对在http请求体重发送给服务器;如果enctype 属性为"multipart/form-data",则以消息的形式发送给服务器。
application/x-www-form-urlencoded 形式的参数其实很像用 get 发送的,但是 get 没有body,所有get请求是直接放在尾部的
相关知识:express自建服务器代码需要注意的
需要引入 bodyParser 库,不然 express 回调里的 req 里面没有 body。
const bodyParser = require('body-parser')
// 支持 application/x-www-form-urlencoded 格式
app.use(bodyParser.urlencoded({ extended: true }));
// 支持 application/json 格式
app.use(bodyParser.json())
参考文档
POST提交数据之---Content-Type的理解
HTTP中的Content-Type
HTTP请求中 request payload 和 formData 区别?
为什么上传文件要使用multipart/form-data
MDN:Content-Type