导航
Content-Type
:
application/json
params
data
Content-Type: application/json
: 请求体中的数据会以 json 字符串的形式发送到后端
Access-Control-Allow-Headers
Content-Type: application/x-www-form-urlencoded
:请求体中的数据会以普通表单形式(键值对)发送到后端Content-Type: multipart/form-data
: 它会将请求体的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件{
url: '/user',
method: 'get', // default
baseURL: '<https://some-domain.com/api>',
// 'transformRequest' 允许在请求数据被发送到服务器之前对其进行更改
// 这只适用于请求方法 'PUT'、'POST'、'PATCH' 和 'DELETE'
// 必须 return 一个 string 或者 Buffer, ArrayBuffer, FormData or Stream 的实例
// 你可以修改header对象
transformRequest: [function (data, headers) {
// 执行想要转换数据的任何操作
return data;
}],
// 'transformResponse' 在传递给 then/catch 前,允许修改响应数据
transformResponse: [function (data) {
// 执行想要转换数据的任何操作
return data;
}],
// 'headers' 是要发送的自定义头信息
headers: {'X-Requested-With': 'XMLHttpRequest'},
// 'params' 是与请求一起发送的URL参数
// 必须是 普通对象 或 URLSearchParams 对象
// 注意: 如果参数为 null 或 undefined ,则不会在 URL 中呈现
params: {
ID: 12345
},
// 'paramsSerializer' 是一个负责序列化 'params' 的可选函数
paramsSerializer: function (params) {
return Qs.stringify(params, {arrayFormat: 'brackets'})
},
// 'data' 是作为请求体发送的数据
// 仅适用于请求方法 'PUT'、'POST'、'DELETE' 和 'PATCH'
// 当没有设置 'transformRequest' 时,必须是以下类型之一:
// - string, 普通对象, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器只支持: FormData, File, Blob
// - Node 只支持: Stream, Buffer
data: {
firstName: 'Fred'
},
// 'timeout' 指定请求超时前的毫秒数
// 如果请求时间超过 'timeout',则请求将被中止
timeout: 1000, // 默认值是 `0`
// `withCredentials` 当前请求为跨域类型时是否在请求中协带cookie
withCredentials: false, // 默认
// `responseType` indicates the type of data that the server will respond with
// options are: 'arraybuffer', 'document', 'json', 'text', 'stream'
// browser only: 'blob'
responseType: 'json', // default
// 'validateStatus' 定义是否 resolve 或 reject 给定 HTTP 响应状态码的 Promise
// 如果此方法返回 `true` (或者设置成 `null/undefined`), 则 Promise 判定为 resolve;
// 否则 Promise 会被 reject.
validateStatus: function (status) {
return status >= 200 && status < 300; // 默认 200、300 间才走 then,否则 catch
},
// 'cancelToken' 用来取消 ajax 请求
cancelToken: new CancelToken(function (cancel) {
}),
}
async getStudents() {
const data = await axios({
url: '<http://localhost:3000/students>',
method: 'get',
params: {
id: 3
},
});
console.log(data);
}
打印 data 后我们会发现,真正的数据在 data 下的 data 中 :
通过常规三种方式设置 Content-Type
都无效:
// 全局:
axios.defaults.headers.get['Content-Type'] = 'application/x-www-form-urlencoded';
// 实例中:
async getStudents() {
const data = await axios({
url: '<http://localhost:3000/students>',
method: 'get',
params: {
id: 3
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
console.log(data);
}
// 拦截器中:
axios.interceptors.request.use((config) => {
config.headers.get['Content-Type'] = 'application/x-www-form-urlencoded';
return config;
})
最后在查看 axios 源码时发现在没有设置 requestData
(也就是 config.data)并且设置 content-type 时,会把 content-type
删除:
// Add headers to the request
if ('setRequestHeader' in request) {
utils.forEach(requestHeaders, function setRequestHeader(val, key) {
if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {
// Remove Content-Type if data is undefined
delete requestHeaders[key];
} else {
// Otherwise add header to the request
request.setRequestHeader(key, val);
}
});
}
这么做的原因在于是 get 请求本身是不需要 Content-Type
的(get 请求在 不自定义headers 时是简单请求),但在知道源码的情况下,我们可以通过手动设置 data
来不走它此处的 if :
axios.interceptors.request.use((config) => {
if (config.method === 'get') {
config.data = true;
config.headers.get['Content-Type'] = 'application/x-www-form-urlencoded';
}
console.log(config.headers);
return config;
})
或者
async getStudents() {
const data = await axios({
url: '<http://localhost:3000/students>',
method: 'get',
params: {
id: 3
},
data: true,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
}
这样就能成功设置上了:
async getStudents() {
const data = await axios({
url: '<http://localhost:3000/students>',
method: 'get',
params: {
id: 3
},
headers: {
'X-Lance': 'Lance',
}
});
console.log(data);
}
让后端具备 post 能力:
const bodyParser = require('body-parser');
const app = express();
// 为 true 时将使用 qs 库处理数据,通常不需要
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
const params = new URLSearchParams();
params.append("id", 1);
params.append("test", 'Lance');
const data = await axios({
url: '<http://localhost:3030/teacher>',
method: 'post',
data: params,
});
application/x-www-form-urlencoded
配合 qs.stringify
const data = await axios({
url: '<http://localhost:3000/teacher>',
method: 'post',
data: qs.stringify({
id: 1,
test: 'Lance'
}),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
或者使用 axios.post
const data = await axios.post(
'<http://localhost:3000/teacher>',
qs.stringify({ id: 1, test: 'Lance' }),
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
)
请求参数是字符串形式:
application/json
,需要后端配合const data = await axios({
url: '<http://localhost:3000/teacher>',
method: 'post',
data: { id: 1 },
});
console.log(data);
后端设置 Access-Control-Allow-Headers
:
app.all('*', (req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-methods', 'GET,POST');
res.header('Access-Control-Allow-Headers', 'Origin,X-Requested-With,Content-Type,Accept');
next();
})
前端请求:
参数:
multipart/form-data
配合 new FormData
上传图片前端代码:
<input
type="file" name="img" id="img"
@change="changeFile"
accept="image/*">上传图片
async changeFile(e) {
console.log(e.target.files);
const file = e.target.files[0];
let formData = new FormData();
formData.append("avatar", file);
const data = await axios({
url: '<http://localhost:3030/uploadImg>',
method: 'post',
data: formData
})
console.log(data);
}
后端代码:
需要安装 multer 包帮助我们实现文件上传
const express = require('express');
const { resolve } = require('path');
const { readFileSync } = require('fs');
const bodyParser = require('body-parser');
const multer = require('multer');
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// 通过 filename 属性定制
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './upload/'); // 保存的路径,备注:需要自己创建
},
filename: function (req, file, cb) {
// 将保存文件名设置为 字段名 + 时间戳,比如 logo-1478521468943
cb(null, file.originalname + '-' + Date.now());
}
});
const upload = multer({ storage })
...
app.post('/uploadImg', upload.single('avatar'), (req, res) => {
res.send({
code: 1,
msg: '上传成功'
})
})
app.listen('3030', () => {
console.log('start 3030');
});
<template>
<div id="app">
<input
type="file" name="img" id="img"
@change="changeFile"
accept="image/*">上传图片
</div>
</template>
<script>
import qs from 'qs'
export default {
name: 'App',
mounted() {
axios.interceptors.request.use((config) => {
// 为了让 get 请求也能设置 content-type
// if (config.method === 'get') {
// config.data = true
// config.headers.get['Content-Type'] = 'application/x-www-form-urlencoded';
// }
// if (config.method === 'post') {
// config.headers.post['Content-Type'] = 'application/json';
// }
console.log(config.headers);
return config;
})
// this.getStudents();
this.getTeacherById(1);
},
methods: {
async getStudents() {
const data = await axios({
url: '<http://localhost:3030/students>',
method: 'get',
params: {
id: 3
},
headers: {
// 'X-Lance': 'Lance',
// 'Content-Type': 'application/x-www-form-urlencoded'
}
});
console.log(data);
},
async getTeacherById(id) {
const params = new URLSearchParams();
params.append("id", 1);
params.append("test", 'Lance');
const data = await axios({
url: '<http://localhost:3030/teacher>',
method: 'post',
data: params,
});
// const data = await axios({
// url: '<http://localhost:3030/teacher>',
// method: 'post',
// data: qs.stringify({
// id
// }),
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded'
// }
// });
// const data = await axios.post(
// '<http://localhost:3030/teacher>',
// qs.stringify({ id, test: 'Lance' }),
// {
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded'
// }
// }
// )
// const data = await axios({
// url: '<http://localhost:3030/teacher>',
// method: 'post',
// data: { id, test: 'Lance' },
// });
console.log(data);
},
async changeFile(e) {
console.log(e.target.files);
const file = e.target.files[0];
let formData = new FormData();
formData.append("avatar", file);
const data = await axios({
url: '<http://localhost:3030/uploadImg>',
method: 'post',
data: formData
})
console.log(data);
}
}
}
</script>
<style lang="scss">
</style>
const express = require('express');
const { resolve } = require('path');
const { readFileSync } = require('fs');
const bodyParser = require('body-parser');
const multer = require('multer');
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// const upload = multer({ dest: 'upload/' });
// 通过 filename 属性定制
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './upload/'); // 保存的路径,备注:需要自己创建
},
filename: function (req, file, cb) {
// 将保存文件名设置为 字段名 + 时间戳,比如 logo-1478521468943
cb(null, file.originalname + '-' + Date.now());
}
});
const upload = multer({ storage })
app.all('*', (req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-methods', 'GET,POST');
res.header('Access-Control-Allow-Headers', 'Origin,X-Requested-With,Content-Type,Accept');
next();
})
app.get('/students', (req, res) => {
const data = readFileSync(resolve(__dirname, './data/students.json'), 'utf8');
res.send(JSON.parse(data));
})
app.post('/teacher', (req, res) => {
const data = JSON.parse(readFileSync(resolve(__dirname, './data/teacher.json'), 'utf8'));
const { id } = req.body;
res.send(data.find(v => v.id == id) || {
code: 0,
msg: '未找到'
});
})
app.post('/uploadImg', upload.single('avatar'), (req, res) => {
res.send({
code: 1,
msg: '上传成功'
})
})
app.listen('3030', () => {
console.log('start 3030');
});