前后端联调编码格式探究

前后端联调的时候经常要约定数据交互的编码格式;这里我们所说的编码格式即是————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

posted @ 2020-09-22 14:32  海客无心x  阅读(308)  评论(0编辑  收藏  举报