一、Request 的Content-Type
我们在开发的过程中需要注意客户端发送请求(Request)时的Content-Type设置,特别是使用ajax的时候,如果设置得不准确,很有可能导致请求失败。
实际开发中,常用的类型有:
如果是一个restful接口(json格式),一般将Content-Type设置为application/json; charset=UTF-8;
如果是文件上传,一般Content-Type设置为multipart/form-data
如果普通表单提交,一般Content-Type设置为application/x-www-form-urlencoded
二、Response 的Content-Type
服务端响应(Response)的Content-Type最好也保持准确,虽然一般web开发中,前端解析响应的数据不会根据Content-Type,并且服务端一般能自动设置准确的Content-Type,但是如果乱设置某些情况下可能会有问题,比如导出文件,打开图片等。
一般情况下不需要显示设置;
如果是文件导出,Content-Type 设置为 multipart/form-data,并且添加一个Content-Disposition设置为attachment;fileName=文件.后缀。
注:
1、Content-Disposition是Content-Type的扩展,告诉浏览器弹窗下载框,而不是直接在浏览器里展示文件。因为一般浏览器对于它能够处理的文件类型,如txt,pdf 等,它都是直接打开展示,而不是弹窗下载框。
2、未设置response的Content-type的情况,客户端将json数据当成普通文本
content-type →text/html;charset=UTF-8
3、如果在spring项目里使用@ResponseBody,Spring会将响应的Content-Type设置为application/json;charset=UTF-8;,可能会导致文件无法导出。
vue和axios中的content-type
在项目中调用接口,通常是以对象的数据格式传给自己封装的http请求函数的。
1. application/json
现在的前后端分离项目基本上都是使用的这个进行数据传递。
axios默认Content-type是采用application/json;charset=UTF-8,无需设置直接把对象传进去即可
当然,也可以在请求拦截器中转化成json后再发请求(但是不能用qs.stringify):
config.data = JSON.stringify(config.data)
2. application/x-www-form-urlencoded
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
用于表单的提交。值得注意的是,ajax 中(不是axios哈), contentType都是默认的值:application/x-www-form-urlencoded。
特点是提交的参数按照 key1=val1&key2=val2 的方式进行编码,key 和 val 会进行了 URL 转码。
而要实现这种参数的序列化,最简单的方法是引入qs库。做如下的配置。
import Qs from "qs"
// 创建axios实例
const service = axios.create({
baseURL: process.env.VUE_APP_baseUrl,
timeout: 5000,
...//其他配置
//transformRequest用来对请求参数提前进行处理
transformRequest: [data => Qs.stringify(data, { indices: true })]
//Qs.stringify将参数序列化成key=value&key=value的形式,indices: true是配置参数有传数组的时候,以下标的形式
})
比如说,当我们传递的参数是:
{
title:'标题',
list:[1,2,3]
}
则会被转化成:title=标题&list[0]=1&list[1]=2&list[2]=3的形式。
Qs.stringify(data, { indices: true }//这个如果用false的话。传数组就是title=标题&list=1&list=2&list=3的形式了,也就是不带索引。
结合上文,在content-tyoe=application/x-www-form-urlencoded时,我们在页面中传的是对象,然后通过Qs.stringify把参数转换成key=value的形式了,这才可以发出正确的http请求。
3. multipart/form-data
这也是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,就要让 form 的 enctype 等于这个值。这种方式一般用来上传文件,各大服务端语言对它也有着良好的支持。这个和application/x-www-form-urlencoded的区别在于一个适合传字段键值,一个适合传文件。
qs.sringify和JSON.stringify的区别
假设我要提交的数据是:
var a = {name:'hehe',age:10};
qs.stringify序列化结果如下
name=hehe&age=10
而JSON.stringify序列化结果如下:
"{"a":"hehe","age":10}"
项目中的使用
项目中有多个接口,后端的接口设计的大部分是application/x-www-form-urlencoded类型的content-type,有少许application/json,可以在全局axios中配置content-type为application/x-www-form-urlencoded。在拦截器中进行判断,需要分类下,使用application/x-www-form-urlencoded的时候,需要key-value序列化处理,而另一种application/json的则不需要。