Axios兼容json和blob格式处理办法
日常开发经常会遇到文件请求的需求,那如何优雅地处理正常场景下获取二进制文件,以及异常场景反馈异常信息呢
先说结论:
前端请求时使用responseType: 'blob'
预先声明。
- 正常场景:后端返回二进制文件时添加文件类型Header如:
Content-Type : application/octet-stream
,此时前端获取内容即为二进制文件- 异常场景:后端添加
Content-Type : application/json
直接返回带有异常信息的JSON。此时,前端需要将blob对象转JSON
1. Axios简介
Axios 是一个基于promise的网络请求库。除了支持Promise的API,还支持取消请求和超时处理,支持自动序列化,支持请求和响应的拦截。使用简单,功能强大
使用示例:
- 发起一个post请求
1
2
3
4
5
6
7
8axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
}); - 用GET请求获取远程图片
1
2
3
4
5
6
7
8axios({
method: 'get',
url: 'http://bit.ly/2mTM3nY',
responseType: 'stream'
})
.then(function (response) {
response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
});
2. Axios前端处理
1 | import axios from 'axios' |
3. 后端响应
ResponseEntity 是Spring框架中用于表示HTTP响应的实体,它封装了响应的状态码、响应头和响应体内容。它可以在控制器方法中用来返回响应,具有更高的灵活性和可控制性
1 |
|
4. 其他
- 按照前面所说,是不是可以在前端请求时候,不要类型声明。然后它会自动转换成你想要的类型?
很遗憾, 我测试了没有。不声明类型的时候,正常返回二进制的时候,js判断类型也不是blob,应该是当成默认的字符串处理了。 - 是不是同样声明接受json,然后字符串转二进制。理论上可行,但实际上大部分时候(正常场景)都需要将字符串转二进制是不合理的。
- 后端在返回前端时候,是否应该设置500或者其他的状态码?这个看各自的编码规范,需要注意的是,Axios提供了请求和响应拦截器。如果在response拦截器中对响应状态码有特殊处理,请注意适配。参考:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
return response;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
}); - 由于axios支持finally,因此最好是处理error,并在finally中定义好回调。以下是增加一个loading遮罩的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29// 调用
const loading = this.$loading({ // 声明一个loading对象
lock: true, // 是否锁屏
text: '正在下载...', // 加载动画的文字
spinner: 'el-icon-loading', // 引入的loading图标
background: 'rgba(0, 0, 0, 0.7)', // 背景颜色
target: '.sub-main', // 需要遮罩的区域
body: true,
customClass: 'mask' // 遮罩层新增类名
})
this.$download.downloadById(row.id, function () {
loading.close()
});
// 封装
downloadById(directoryId, callback) {
axios({
method: 'get/post',
url: url,
responseType: 'blob',
headers: { 'Authorization': ''}
}).then((res) => {
}).catch(err => {
}).finally(() => {
callback()
});
}