最近遇到一个需求,就是前端发送post请求获取后端的excel文件,并且前端实现下载导出到本地的功能。
前端页面就长上面那样,一个批量导出功能,用户勾选之后,前端通过接口把id和其他的参数传给后端,接口调用方法这里需要注意的是,这里必须设置responseType: ‘blob’
,后端返回来一个文件流,然后前端通过封装的方法实现下载导出,前端导出方法如下:
这里前端通过blobDownloads实现下载:
前端需要引入这个js
import localDownloadUtil from "@/utils/localDownloadUtil.js";
然后我们看看这个js里封装了两个下载方法,一种是iframe下载,一种是二进制文件下载,这里我们选择了二进制文件下载:
/** * 本地下载一个文本文件。 * @link https://ourcodeworld.com/articles/read/189/how-to-create-a-file-and-generate-a-download-with-javascript-in-the-browser-without-a-server * @param filename {string} * @param text {string} */// function download (filename, text) {// const element = document.createElement('a')// element.setAttribute('href', `data:text/plain;charset=utf-8,${encodeURIComponent(text)}`)// element.setAttribute('download', filename)// element.style.display = 'none'// document.body.appendChild(element)// element.click()// document.body.removeChild(element)// }// iframe下载文件,没又身份验证的get接口可以使用function iframeDownloads(lastUrl){ var downloadFileUrl = window.g.API_URL + lastUrl var elemIF = document.createElement("iframe"); elemIF.src = downloadFileUrl; elemIF.style.display = "none"; document.body.appendChild(elemIF);}// 设备二进制文件function blobDownloads (data, fileName) { if (!data) { return } // type: 'application/vnd.ms-excel' const url = window.URL.createObjectURL(new Blob([data])) const link = document.createElement('a') link.style.display = 'none' link.href = url link.setAttribute('download', fileName) document.body.appendChild(link) link.click() window.URL.revokeObjectURL(url) document.body.removeChild(link)// 下载完毕删除a标签}export default { // download, blobDownloads, iframeDownloads}
还有一种情况是后端返回的不是文件流或文件对象,而返回的就是一个blob文件,然后文件名带文件格式的字符串,如下图是后端返回的结果:
那这个请求就不能用我们封装的请求去发请求了,需要我们手动写个axios去发请求,并将返回的结果通过window.open来打开下载:
整个页面完整代码如下:
<template> <div class="mainBox"> <!-- 仿冒日志 --> <el-card shadow="always" :style="'height:100%;overflow:auto;'"> <div class="centerLeftBox"> <search-form ref="searchForm_Board" @reset="reset_Board" @handleSubmit="handleSubmitSearch_Board" :formData="formData_Board" :isInline="true" :searchConfig="searchConfig_Board" > </search-form> </div> </el-card> <div style="height:10px;"></div> <el-card> <commonTable :tableHead="tableHead_Board" :tableData="tableData_Board" :selectionFlag="true" :toolBoxFlag="true" :resizable="true" :dataFiter="true" :xuhaoFlag="false" :dropdownList="dropdownList" @selectAction="selectAction" :addBtn="false" :tableLoading="tableLoading_Board" :showListD="showListD_Board" :maxHeight="'458'" :freeElfFlag="false" :rightBtnList="rightBtnList" ref="commonTable" > <template slot-scope="scope" slot="freeElf"> <!-- <el-button size="mini" type="text" @click="goFakeLog(scope.scope.row)" v-authbuttons:[otherAuth] >仿冒日志</el-button > --> </template> </commonTable> <div style="height:10px;"></div> <el-pagination class="tac page-style" background @size-change="BoardChangeSize" @current-change="BoardCurrentChange" :current-page.sync="BoardPageObj.page" :page-sizes="[10, 20, 30, 40, 50]" :page-size.sync="BoardPageObj.page_size" :current.sync="BoardPageObj.page" layout="total, sizes, prev, pager, next, jumper" :total="BoardPageObj.total" :style="'text-align:left;'" ></el-pagination> </el-card> <el-dialog title="处理仿冒" center :visible.sync="isShowModal" @close="closeModal" :show-close="true" :close-on-click-modal="false" :width="'800px'" > <fake-edit v-if="isShowModal" ref="fakeEdit" :formData="FakeObj" :newValue="newValue" @closeFake="closeFake" /> <div slot="footer" class="dialog-footer"> <el-button @click="isShowModal = false">取 消</el-button> <el-button type="primary" :loading="saveLoading" @click="editOk" >处 理</el-button > </div> </el-dialog> </div></template><script>import searchForm from "@/components/search-form";import commonTable from "@/components/common-table";import { getFakelogList } from "@/api/systemControl.js";import { getBoardFakeCommonData } from "@/api/asset.js";import localDownloadUtil from "@/utils/localDownloadUtil.js";import { getToken } from "@/utils/auth";import axios from "axios";export default { name: "PendingProcessing", components: { commonTable, searchForm }, data() { return { formData_Board: {}, searchConfig_Board: [ { type: "select", label: "操作类型", props: "log_pd_result", labelWidth: 95, options: [], changeSearch: true, changeSearch: true, defaultPropsLabel: "val", defaultPropsValue: "key" }, { type: "input", label: "设备IP", props: "ip", labelWidth: 95 }, { type: "input", label: "设备MAC", props: "old", labelWidth: 95 }, { type: "input", label: "当前MAC", props: "new", labelWidth: 95 }, { type: "timeBox", label: "时间范围", props: "time" }, { type: "btnList" } ], tableHead_Board: [ { label: "设备IP", prop: "ip", type: "normal", sortable: false }, { label: "设备MAC", prop: "old", type: "normal", sortable: false }, { label: "仿冒原因", prop: "cause_str", type: "normal", sortable: false }, { label: "当前MAC", prop: "new", type: "normal", sortable: false }, { label: "操作人账户", prop: "user_name", type: "normal", sortable: false }, { label: "操作类型", prop: "pd_result_str", type: "normal", sortable: false }, { label: "更新时间", prop: "c_time", type: "normal", sortable: false } ], tableData_Board: [], tableLoading_Board: false, showListD_Board: [ "ip", "old", "cause_str", "new", "user_name", "c_time", "pd_result_str" ], BoardPageObj: { page: 1, page_size: 10, total: 0 }, editAuth: "update,FakeManage", otherAuth: "others,FakeManage", FakeObj: {}, isShowModal: false, saveLoading: false, newValue: "", dropdownList: [ // {actionName:'fileAction',label:'归档',iconClass:'el-icon-s-cooperation',actionConfirm:'是否确定归档这些数据'}, // {actionName:'deleteAction',label:'删除',iconClass:'el-icon-delete',actionConfirm:'是否确定删除这些数据'}, { actionName: "downLoadBatch", label: "批量导出", type: "primary", iconClass: "el-icon-download", actionConfirm: "是否确定导出这些数据" } // { // actionName: "editGroup", // label: "移动分组", // type: "primary", // iconClass: "el-icon-s-cooperation", // actionConfirm: "是否确定移动这些数据", // flag: true, // }, // {actionName:'editGroupHigh',label:'高级分组',type:'primary',iconClass:'el-icon-s-grid',actionConfirm:'', flagEx: true,}, ], rightBtnList: [ { actionName: "downAll", label: "一键导出", type: "primary", iconClass: "el-icon-download", actionConfirm: "", flagEx: true } ] }; }, created() { this.formData_Board.ip = this.$route.query.fakeIp; this.handleSubmit_Board({}, true); this.getCommonData(); }, methods: { // 每页显示数变动 BoardChangeSize(pageSize) { // console.log("条数", pageSize); this.BoardPageObj.page_size = pageSize; this.handleSubmit_Board({}, true); }, BoardCurrentChange(page) { // console.log("当前页", page); this.BoardPageObj.page = page; this.handleSubmit_Board({}, false); }, // 获取交换机列表数据 handleSubmit_Board(data, flag) { if (flag) { this.BoardPageObj.page = 1; } let dataT = JSON.parse(JSON.stringify(this.formData_Board)); dataT.page = this.BoardPageObj.page; dataT.page_size = this.BoardPageObj.page_size; if (dataT.time && dataT.time.length > 0) { dataT.start_time = dataT.time[0]; dataT.end_time = dataT.time[1]; delete dataT.time; } this.tableLoading_Board = true; getFakelogList(dataT) .then(res => { this.tableData_Board = res.data.list; this.BoardPageObj.total = res.data.total; this.tableLoading_Board = false; }) .catch(err => {}); }, // 重置筛选项 reset_Board() { this.formData_Board = {}; this.handleSubmit_Board({}, true); }, handleSubmitSearch_Board(data) { this.handleSubmit_Board(data, true); }, editData(item) { this.isShowModal = true; this.newValue = item.new; this.FakeObj = { ...item, process_type: "1" }; }, closeModal() { this.isShowModal = false; }, closeFake() { this.isShowModal = false; this.reset_Board(); }, editOk() { this.$nextTick(() => { this.$refs.fakeEdit.submit(); }); }, // 数据批量操作,判断和提示都已经做好了 selectAction(data) { var idList = []; var idString = ""; for (let index = 0; index < data.data.length; index++) { const element = data.data[index]; idList.push(element.id); idString = idString + element.id; if (index + 1 !== data.data.length) { idString = idString + ","; } } var dataT = { ids: idString }; var that = this; if (data.name === "fileAction") { // 归档 // assetsdevinfofiling(dataT).then((res) => { // that.$message({ message: "归档成功", type: "success" }); // this.handleSubmitSearch({}); // }); } else if (data.name === "deleteAction") { // if (data.data.length <= 1) { // assetsListDelete(dataT.ids).then((res) => { // that.$message({ message: "删除成功", type: "success" }); // this.handleSubmitSearch({}); // }); // } else { // multipleDelete(dataT.ids).then((res) => { // that.$message({ message: "删除成功", type: "success" }); // this.handleSubmitSearch({}); // }); // } } else if (data.name === "editGroup") { // var showListFenzu = []; // for (let index = 0; index < data.data.length; index++) { // const element = data.data[index]; // showListFenzu.push(element.id); // } // this.editAssetGroutIdList = showListFenzu; // this.treeTitle = "设置资产分组"; // this.treeFlag = true; } else if (data.name === "downLoadBatch") { // dataT.id_ls = JSON.stringify(idList); dataT.filename = "仿冒文件"; dataT.pending_flag = "1"; dataT.ip = that.formData_Board.ip ? that.formData_Board.ip : ""; dataT.old = that.formData_Board.old ? that.formData_Board.old : ""; dataT.new = that.formData_Board.new ? that.formData_Board.new : ""; dataT.pd_result = ""; this.tableLoading_Board = true; let datatFormdata = new FormData(); for (var key in dataT) { datatFormdata.append(`${key}`, dataT[key]); } axios({ url: `${window.g.API_URL}/counterfeits/log/export/`, method: "post", data: datatFormdata, headers: { "Content-Type": "multipart/form-data", Authorization: "Bearer " + getToken() } }) .then(res => { // console.log("导出", res); if (res.data.code == 200) { let filename = res.data.data; window.open(`${window.g.API_URL}/media/${filename}`); this.$message.success("批量导出成功", 4000); this.$nextTick(() => { this.$refs.commonTable.resetSelect(); this.$refs.commonTable.clearSelection(); }); this.tableLoading_Board = false; } }) .catch(err => {}); } else if (data.name === "downAll") { this.tableLoading_Board = true; let query = { filename: "仿冒文件", ids: "all" }; let queryFormdata = new FormData(); for (var k in query) { queryFormdata.append(`${k}`, query[k]); } axios({ url: `${window.g.API_URL}/counterfeits/log/export/`, method: "post", data: queryFormdata, headers: { "Content-Type": "multipart/form-data", Authorization: "Bearer " + getToken() } }) .then(res => { // console.log("导出", res); if (res.data.code == 200) { let filename = res.data.data; window.open(`${window.g.API_URL}/media/${filename}`); this.$message.success("一键导出成功", 4000); this.$nextTick(() => { this.$refs.commonTable.resetSelect(); this.$refs.commonTable.clearSelection(); }); this.tableLoading_Board = false; } }) .catch(err => {}); } }, goFakeLog(item) { this.$router.push({ path: "FakeLog", query: { fakeIp: item.ip } }); }, //获取公共数据 getCommonData() { getBoardFakeCommonData() .then(res => { // console.log("获取公共数据", res); this.$nextTick(() => { this.searchConfig_Board[0].options = res.data.log_pd_result; }); }) .catch(err => {}); } }};</script>