获取二进制流文件api编写
这里的后端是使用Spring Boot框架编写的一个项目
我这里是使用的封装,然后调用的方式:
首先编写一个工具类:
名字为downloadRequest.js
代码注释如下:
import axios from "axios";
/**
* 文件下载的api封装
*/
// 创建一个axios对象
const service = axios.create({
// 请求的基准路径
baseURL: "http://localhost:8082/api/v1",
// 添加返回响应的类型
responseType: "arraybuffer",
});
// 请求拦截器
service.interceptors.request.use(
(config) => {
// 获取用户的token 添加到请求头(这里是存在会话中的用户token)
config.headers["Authorization"] = window.sessionStorage.getItem("tokenStr");
return config;
},
(error) => {
// 打印错误信息
console.log(error);
}
);
// 响应拦截器
service.interceptors.response.use(
(resp) => {
console.log(resp);
// 获取响应头信息
const headers = resp.headers;
// 判断请求头中数据是不是json格式数据
let reg = RegExp(/application\/json/);
if (headers["content-type"].match(reg)) {
// 是的话使用这个函数解析
resp.data = unitToString(resp.data);
} else {
// 不是的话使用 安装的第三方插件解析
let fileDownload = require("js-file-download");
// 获取响应中返回的字符串
// console.log(headers["content-disposition"]);
let fileName = headers["content-disposition"]
.split(";")[1]
.split("filename=")[1];
let contentType = headers["content-type"];
// 使用下面的方法解析响应的数据
fileName = decodeURIComponent(fileName);
fileDownload(resp.data, fileName, contentType);
}
},
(error) => {
console.log(error);
}
);
// 装换json格式数据
function unitToString(unitArray) {
let encodedString = String.fromCharCode.apply(
null,
new Uint8Array(unitArray)
);
let decodedString = decodeURIComponent(escape(encodedString));
return JSON.parse(decodedString);
}
// 编辑api接口 (如果使用这个请注释掉最上面的[baseURL],然后直接在vue文件中引入 downloadRequest 方法直接调用)
// let base = "http://localhost:8082/api/v1";
// export const downloadRequest = (params) => {
// return service({
// method: "GET",
// url: `${base}/employee/basic/export`,
// params,
// });
// };
// 导出
export default service;
我使用的方法是模块化方法,便于后期的二次开发和维护。因此呢,我建立专门的API的js文件,引入我封装的工具类
代码注释如下:
import service from "../utils/download";
/**
* 员工接口api
*/
/**
* 导出员工表
* @param {*} params
* @returns
*/
export const downloadRequest = (data) => {
return service({
method: "GET",
url: `/employee/basic/export`,
data,
});
};
最后在.vue文件中引入这个方法并且调用,无需传参
代码如下:(由于我原来文件中代码较多,因此使用初始化的.vue文件)
<template>
<div class="EmpAdv">
<el-button type="success" icon="el-icon-download" @click="expostData"
>导出数据</el-button
>
</div>
</template>
<script>
import { downloadRequest } from "../../api/emplotee";
export default {
name: "EmpAdv",
data() {
return {};
},
created() {},
methods: {
// 导出员工信息
expostData() {
downloadRequest();
}
}
};
</script>
<style scoped></style>
在这里我出现了一个问题就是在封装好的工具类处理响应的数据的时候,找不到headers中的’content-disposition’
具体问题描述如下:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'split')
at __webpack_exports__.default (download.js?989b:43:1)
问题描述
显示的是这里出错了,我仔细看了看以后自己的后端没有传递这个参数
但是回去检查了一遍,确实传递了呀
然后我又发现,在浏览器调试器 network中居然有这个属性,但是在响应拦截器中居然没有打印出来,邪门滴很呐!!
产生问题原因
跨域(CORS)请求中,被axios封装好的XMLHttpRequest
对象中的方法getResponseHeader()
默认只能获取6个基本的字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma
。因此,需要获取其他的属性,需要后端在响应的时候去在Access-Control-Expose-Headers
中指定content-disposition
属性。
所以这是一个后端的锅,是他没有配置,这个问题去找后端,让他在response中配置放行。
后端解决方案
在controller
层中的二进制流文件下载方法下配置放行属性:
response.setHeader("Access-Control-Expose-Headers", "content-disposition");