直接上 Vue 代码
// 获取后端直接返回的文件流
getBlob(id) {
return new Promise((resolve) => {
const xhr = new XMLHttpRequest();
//按业务配置,填自己的baseURL
xhr.open('POST', this.baseURL + `/oms/summary/downloadPDF/${id}`, true);
xhr.setRequestHeader('x-token', sessionStorage.getItem('x-token'));
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
// 检查下面这一步不能少
xhr.responseType = 'blob';
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response);
}
};
xhr.send();
});
},
//下载文件操作
downloadPDF(id, filename) {
this.getBlob(id).then((res) => {
// 在这里可以设置下载文件格式
let blob = new Blob([res], { type: 'application/pdf' });
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, filename);
} else {
let link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
link.click();
window.URL.revokeObjectURL(link.href);
}
});
},
--可有可无的小故事--
之前项目中同事有写过类似的下载文件,当时项目是基于react的,看了下代码找到专门处理下载的一个js文件,把它挪过来改了改,能跑了,然而!
下载的是个json文件,一看果然是报错了,报了500,后端同学一看,说我忘带token了。
行嘛,加上token继续跑,下载框框一弹,很激动,但仔细一看怎么格式是xml?手动改成pdf可以正常下载,那应该是没定义好下载文件格式!
于是又是上网一顿搜,一顿找在代码哪个地方加我的格式定义,结果苦苦找了好久都对不上那看着很高深的代码。后来竟是在知乎上找到一个非常简洁的解决方法,我终于决定抛弃冗长的旧代码来试试 。试了一下,没反应,还好答主提醒没有responseType = 'blob'不行,最终结合旧代码再一改,终于成了!感天动地!!
后来反思为什么之前找不到加文件格式的地方,是因为返回来的blob被直接丢去msSaveBlob处理了,没有定义出来quqlet blob = new Blob([res], { type: 'application/pdf' });