常见Content-Type (application/x-www-form-urlencoded,multipart/form-data,application/json)
1. 基础知识
HTTP 协议是以 ASCII 码传输,建立在 TCP/IP 协议之上的应用层规范。规范把 HTTP 请求分为三个部分:状态行、请求头、消息主体。 协议规定,POST提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么编码方式。服务端通常是根据请求头(headers)中的Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。所以说到 POST 提交数据方案,包含了Content-Type 和消息主体编码方式两部分 。
application/json 格式
-POST /some-path HTTP/1.1 Content-Type: application/json
{ “foo” : “bar”, “name” : “John” }
application/x-www-form-urlencoded 格式
POST /some-path HTTP/1.1
Content-Type: application/x-www-form-urlencoded
foo=bar&name=John
1. axios 之默认请求格式 application/json
原始的Axios请求方式
axios.request(config)
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
},
timeout: 1000,
...//其他相关配置
});
axios.get(url[, config])
axios.get('demo/url', {
params: {
id: 123,
name: 'Henry',
},
timeout: 1000,
...//其他相关配置
})
axios.post(url[, data[, config]])
axios.post('demo/url', {
id: 123,
name: 'Henry',
},{
timeout: 1000,
...//其他相关配置
})
常用范围:复杂的请求参数,及RESTFull 风格架构的系统(比如前后端分离的SpringBoot+vue/react)
在Vue中前端请求配置文件axios.js:
import axios from 'axios'
import { Notification, MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
import errorCode from '@/utils/errorCode'
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API,
// 超时
timeout: 60000
})
// request拦截器
service.interceptors.request.use(config => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?';
for (const propName of Object.keys(config.params)) {
const value = config.params[propName];
var part = encodeURIComponent(propName) + "=";
if (value !== null && typeof(value) !== "undefined") {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
let params = propName + '[' + key + ']';
var subPart = encodeURIComponent(params) + "=";
url += subPart + encodeURIComponent(value[key]) + "&";
}
} else {
url += part + encodeURIComponent(value) + "&";
}
}
}
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
return config
}, error => {
console.log(error)
Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use(res => {
// 未设置状态码则默认成功状态
const code = res.data.code || 200;
// 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default']
if (code === 401) {
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
store.dispatch('LogOut').then(() => {
location.href = '/index';
})
})
} else if (code === 500) {
Message({
message: msg,
type: 'error'
})
return Promise.reject(new Error(msg))
} else if (code !== 200) {
Notification.error({
title: msg
})
return Promise.reject('error')
} else {
return res.data
}
},
error => {
console.log('err' + error)
let { message } = error;
if (message == "Network Error") {
message = "后端接口连接异常";
}
else if (message.includes("timeout")) {
message = "系统接口请求超时";
}
else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常";
}
Message({
message: message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
export default service
进一步封装:
import request from ‘@/utils/request’
import { praseStrEmpty } from “@/utils/ruoyi”;
// 查询用户列表
export function listUser(query) {
return request({
url: ‘/system/user/list’,
method: ‘get’,
params: query
})
}
// 查询用户详细
export function getUser(userId) {
return request({
url: ‘/system/user/’ + praseStrEmpty(userId),
method: ‘get’
})
}
// 新增用户
export function addUser(data) {
return request({
url: ‘/system/user’,
method: ‘post’,
data: data
})
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LdOehA99-1668070387557)(C:/Users/a/AppData/Roaming/Typora/typora-user-images/image-20221110165128749.png)]
- axios 之 application/x-www-form-urlencoded
application/x-www-form-urlencoded:是最常见的 POST 提交数据的方式,浏览器的原生表单如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据,它是未指定属性时的默认值。 数据发送过程中会对数据进行序列化处理,以键值对形式?key1=value1&key2=value2的方式发送到服务器。 数据被编码成以 ‘&’ 分隔的键-值对, 同时以 ‘=’ 分隔键和值。非字母或数字的字符会被 percent-encoding。在axios中当请求参数为qs.stringify(data)时,会以此方式提交数据。后台如果使用对象接收的话,可以自动封装成对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-imonR7kJ-1668070387558)(C:/Users/a/AppData/Roaming/Typora/typora-user-images/image-20221110165150796.png)]
优势: 所有浏览器都兼容。
问题:在数据结构及其复杂时,服务端数据解析变得很难
3. axios 之 multipart/form-data
常用于post 提交,提交的格式有text 和file 格式,常用于数据量多的表单提交及文件上传
时,会以此方式提交数据。后台如果使用对象接收的话,可以自动封装成对象
[外链图片转存中…(img-imonR7kJ-1668070387558)]
优势: 所有浏览器都兼容。
问题:在数据结构及其复杂时,服务端数据解析变得很难
3. axios 之 multipart/form-data
常用于post 提交,提交的格式有text 和file 格式,常用于数据量多的表单提交及文件上传
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HB1x2U5a-1668070387558)(C:/Users/a/AppData/Roaming/Typora/typora-user-images/image-20221110165222140.png)]