Vue结合后台详解导入导出Excel问题
今天讲讲 前台Vue配合后台(java)导出Excel 后台返回的数据是 二进制文件流 如何将此变为 弹框下载
当时开发呢,我们后台是java 有控件 可以直接将数据导出并生成Excel文件,但是前后台传输是不可能直接传输文件的,是以二进制文件流进行传输的,此时呢就会遇到一个问题,因为是后台,必然会涉及到权限,权限就涉及到token,token传输就会出现限制问题,所以我会列出三种方法
我的是Vue项目~~
1.不需要token的方法
<template>
<div>
<el-button @click="downloadFile" type="primary">导出 Excel</el-button>
<iframe id="ifile" style="display:none"></iframe>
</div>
</template>
<script>
methods:{
// 导出 Excel
downloadFile() {
var dom=document.getElementById('ifile');
dom.src= this.downloadFileUrl +`/pay/exportExcel?userId=${
this.form.userId}&orderNumber=${
this.form.orderNumber}&stime=${
this.form.stime}&etime=${
this.form.etime}&status=${
this.form.status}&payChannel=${
this.form.payChannel}`;
}
},
</script>
这个的意思呢就是写一个类似的隐藏域 ifram 标签独有的特性 , 不明白的可以去W3cschool 查一查, 后面拼接的参数就是导出条件,按个人需要进行,这个亲测有效!
2.第二种就涉及到token了 , 就是使用javascript的内置对象来解析,方法就是使用axios请求 请求过来的二进制文件流进行解析
// 导出 Excel
downloadFile() {
// 这是methods中的方法
downLoadPayListFn({
...this.form}).then(res => {
// 这个是我封装的方法 就是通过axios请求进行拦截 添加token form是data中的数据 也就是筛选条件
const fileName = '测试表格123.xls';
if ('download' in document.createElement('a')) {
// 非IE下载
const blob = new Blob([res], {
type: 'application/ms-excel'});
const elink = document.createElement('a');
elink.download = fileName;
elink.style.display = 'none';
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
URL.revokeObjectURL(elink.href); // 释放URL 对象
document.body.removeChild(elink);
}
})
},
这个blob是js的内置对象 就是将其转化为文件 详情解释可以去查 blob
import fetch from 'utils/fetch';
import Qs from 'qs';
// 导出数据
export function downLoadPayListFn(obj) {
return fetch({
url: '/admin/pay/exportExcel',
method: 'get',
params: obj,
responseType: 'blob',
/* header: {
'Content-Type': "application/x-www-form-urlencoded; charset=utf-8"
} */
});
}
在这里一定要加上 responseType: 'blob',否则不会生效 切记!!!!
看网上写的是这个样子 当然也根据后台返回给你的数据进行展示 我们后台返回的数据没有进行包装 所以直接就是response,搞就完事了.
3.第三种方法 使用form 表单提交 隐藏域使用
<template>
<div id="rechargeRecord">
<!-- 支付管理 -->
<div class="title">
<el-form label-width="100px">
<form class="form" :action="downloadFileUrl+`/pay/exportExcel`" method="post">
<input type="hidden" name="userId" :value="form.userId"> <!-- 用户id -->
<input type="hidden" name="orderNumber" :value="form.orderNumber"> <!-- 订单单号 -->
<input type="hidden" name="stime" :value="form.stime"> <!-- 时间 -->
<input type="hidden" name="etime" :value="form.etime"> <!-- 时间 -->
<input type="hidden" name="status" :value="form.status"> <!-- 交易状态(1开始,2进行中,3失败,4成功) -->
<input type="hidden" name="type" :value="form.type"> <!-- 支付类型(1.扣除 2.返还 3.转换 4.赠送) -->
<input type="hidden" name="ctimeState" :value="form.ctimeState"> <!-- 创建时间状态(1:正序、2:倒序) -->
<input type="hidden" name="payChannel" :value="form.payChannel"> <!-- 支付渠道 -->
<input type="hidden" name="token" :value="token"> <!-- 支付渠道 -->
<input type="submit" value="导出 Excel" @click="submitBtn(event)" class="submit" >
</form>
</el-form>
</div>
</div>
</template>
<script>
import {
getPayListFn, downLoadPayListFn } from 'api/game/money/rechargeRecord';
import {
mapGetters } from "vuex";
import {
getToken } from "utils/auth.js"; // 这是我自己封装的方法 获取token的方法
export default {
data(){
return{
form: {
pageIndex: 1, // 当前页数
pageSize: 10, //请求行数
userId: '', // 用户id
orderNumber: '', // 订单单号
stime: '', // 创建时间(开始)
etime: '', // 创建时间(结束)
status: '', // 交易状态(1开始,2进行中,3失败,4成功)
type: '', // 支付类型(1.扣除 2.返还 3.转换 4.赠送)
ctimeState: '', // 创建时间状态(1:正序、2:倒序)
payChannel: '', // 支付渠道
},
token: getToken() , // 这里获取token
}
},
// 页面一加载的时候
created() {
this.getdata();
},
methods:{
submitBtn(e) {
e.preventDefault(); // 这个必须要有, 不然不生效
return false; // 这个必须要有, 不然不生效
}
},
}
</script>
<style rel="stylesheet/scss" scoped>
.form {
display: inline-block;
border-color: #20a0ff;
margin-left: 0.6rem;
}
.submit {
line-height: 1;
white-space: nowrap;
cursor: pointer;
background: #fff;
border: 1px solid #c4c4c4;
color: #1f2d3d;
margin: 0;
padding: 10px 15px;
border-radius: 4px;
border-color: #20a0ff;
}
</style>
这个就需要后台配合配置一下网关,如果有header中有token的话就去header中取 没有的话就去参数中取,这个亲测好使。