前端通常通过后端接口访问拿到需要下载的文件流。
前端请求后台接口方式要求返回的类型是Blob类型:如下请求方式
// 导出数据
export function exportData(data) {
return axios({
url: `${serverUrl}/b/wecorp/wc-emp-withdrawal-receipt/export`,
method: 'post',
responseType: 'blob',
data
});
}
如果没有数据,后台可能返回的不是文件流,而是一个没有数据的json串,需要做一次判断,没有数据的时候不下载文件流,只提示没有导出数据。使用如下方式判断:
let res = await fundSettlement.exportData(params);
if (res.data && res.data.type === 'application/json') {
res.data.text().then((result) => {
let json = {};
try {
json = JSON.parse(result);
this.$message.error(json.data);
} catch (err) {
throw(err)
}
});
} else {
// res.headers['content-disposition'] = '';
download(res, "资金结算");
}
download()方法是最后下载文件流的方法,“资金结算”是下载的文件名。
具体实现如下:
/**
* 下载文件
* @param {*} res
*/
function download(res, name) {
const blob = new Blob([res.data], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8',
}); // application/vnd.openxmlformats-officedocument.wordprocessingml.document这里表示doc类型
const contentDisposition = res.headers['content-disposition'] || ''; // 从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名;
const patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*');
const result = patt.exec(contentDisposition);
let filename = Array.isArray(result) && result.length > 0 && result[1];
const lastDotIndex = (filename && filename.lastIndexOf('.')) || -1;
let extName = '';
if (lastDotIndex > -1) {
extName = filename.slice(lastDotIndex);
}
if (name) {
filename = name.lastIndexOf('.') > -1 ? name : `${name}${extName || '.xlsx'}`;
}
if (!filename) {
filename = '文件.xlsx';
}
const downloadElement = document.createElement('a');
const href = window.URL.createObjectURL(blob); // 创建下载的链接
const reg = /^["](.*)["]$/g;
downloadElement.style.display = 'none';
downloadElement.href = href;
downloadElement.download = decodeURI(filename.replace(reg, '$1')); // 下载后文件名
document.body.appendChild(downloadElement);
downloadElement.click(); // 点击下载
document.body.removeChild(downloadElement); // 下载完成移除元素
window.URL.revokeObjectURL(href); // 释放掉blob对象
}