前言
记录一下文件下载的两种方式。一种是通过后端返回字节流来下载文件,另一种是通过插件前端自行下载。
方便自己以后CV。
接口返回字节流
template
<template>
<div>
<el-button v-loading="isLoading" @click="downloadExcel"
>click me</el-button
>
</div>
</template>
script
<script>
import TestApi from '@/api/test';
export default {
components: {},
data() {
return {
isLoading: false
};
},
created() {},
methods: {
async downloadExcel() {
const params = {
surveyId: 1732,
userId: 520400
};
const fileInfo = {
fileName: '测试下载文件',
type: 'xlsx'
};
this.isLoading = true;
const res = await TestApi.downloadExcel(params, fileInfo);
this.isLoading = false;
this.$message({
type: res.code === 1 ? 'success' : 'error',
message: res.message
});
}
}
};
</script>
api
import request from '@/utils/request.js';
export default class TestApi {
/**
* Excel 文件导出
* @param {Object} params 入参
* @param {fileInfo} 导出文件名称及类型
* @returns
*/
static async downloadExcel(params, fileInfo) {
const response = await request({
method: 'post',
url: 'api/test/downloadExcel',
params,
responseType: 'blob',
});
const { status, data } = response
if (status !== 200) {
return {
code: 0,
message: '下载失败,请稍后重试'
}
}
try {
// const contentType = response.headers['content-type'];
// const blob = new window.Blob([data], {
// type: contentType
// });
const a = document.createElement('a');
// const href = window.URL.createObjectURL(blob); //创建下载的链接
const href = window.URL.createObjectURL(data); //创建下载的链接
a.href = href;
const { fileName, type } = fileInfo;
a.download = `${fileName}.${type}`;
a.click();
window.URL.revokeObjectURL(href); // 释放掉blob对象
return {
code: 1,
message: '下载成功'
}
} catch (err) {
return {
code: 0,
message: err
}
}
}
}
- 其中
api返回的response见下图
前端通过插件自行下载
现在下载的插件很多,每个插件都有自己的使用方式。
这里我举一下老项目中使用的js-xlsx
// 将 workbook 转为blob 对象
function _wb2blob(workbook) {
const wopts = {
// 要生成的文件类型
bookType: 'xlsx',
// 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
bookSST: false,
type: 'binary'
};
const wbout = XLSX.write(workbook, wopts);
// 字符串转ArrayBuffer
function s2ab(s) {
const buf = new ArrayBuffer(s.length);
const view = new Uint8Array(buf);
for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
return buf;
}
const blob = new Blob([s2ab(wbout)], {
type: 'application/octet-stream'
});
return blob;
}
// 通过 blob 对象下载 excel
function _openDownloadDialog(b, saveName) {
if (typeof b === 'object' && b instanceof Blob) {
const url = URL.createObjectURL(b);
const aLink = document.createElement('a');
aLink.href = url;
aLink.download = saveName || '';
let event;
if (window.MouseEvent) event = new MouseEvent('click');
else {
event = document.createEvent('MouseEvents');
event.initMouseEvent(
'click',
true,
false,
window,
0,
0,
0,
0,
0,
false,
false,
false,
false,
0,
null
);
}
aLink.dispatchEvent(event);
}
}
// 通过 id 获取 Element 的 Table
function _getElementTableStrById(id) {
const wbtable = document.createElement('table');
const tableHeader = document.querySelector(`#${id} .el-table__header thead`);
const tableBody = document.querySelector(`#${id} .el-table__body tbody`);
// 创建节点的拷贝,并返回该副本
const headerClone = tableHeader.cloneNode(true);
const bodyClone = tableBody.cloneNode(true);
wbtable.appendChild(headerClone);
wbtable.appendChild(bodyClone);
return wbtable
}
// 通过传入的 tableStr 创建 table
function _getDefinedTableStr(tableStr) {
const wbtable = document.createElement('table');
wbtable.innerHTML = tableStr;
return wbtable
}
/**
* 下载
* @param {String} id id 为 el-table 绑定 id
* @param {String} fileName 下载文件名称
* @param {String} tableStr table innerHtml
*/
export function downloadExcel({ id, tableStr, fileName }) {
/**
* id 和 tableStr 传一个即可
* id 表示下载的为 el-table
* tableStr 表示下载的自定义表格,需要传一个字符串,格式为`<table>${theadStr}${thbodyStr}</table>`;
*/
const wbTable = tableStr ? _getDefinedTableStr(tableStr) : _getElementTableStrById(id);
// 1-创建工作薄
const workbook = XLSX.utils.book_new();
// 2-创建工作表
const sheet = XLSX.utils.table_to_sheet(wbTable);
// 设置单元格宽度
sheet['!cols'] = new Array(Object.keys(sheet).length).fill({ wpx: 120 });
// 3-将 sheet 添加到 workbook 中
XLSX.utils.book_append_sheet(workbook, sheet, 'sheet1');
// 4-下载
const blob = _wb2blob(workbook);
_openDownloadDialog(blob, `${fileName}.xlsx`);
}
补充
后端返回字节流这块的代码我自己跑过,无报错。
通过插件这个只是大概的思路,具体还要根据项目分析。
最后
- 文章是自己手敲,是对工作日常的总结,如有错误之处,敬请指正
- 如果遇到什么问题就留言吧,能解决大家帮忙一起解决一下