前后端 数据流下载文件
1. 前端取流接口
需要补充 responseType: 'blob'
参数,用来限定响应数据类型。
function loadBlob(params) {
return axios({
method: 'get',
url: '/download',
params,
responseType:'blob',
})
}
2. 接口取值
常规取流后,转为 Blob 类文件对象。
async fetchResource(params) {
try {
const res = await Api.streamDownload(params)
const {data, headers} = res || {}
// 二进制流
const href = window.URL.createObjectURL(new Blob([data]))
const fileName = headers['content-disposition']?.split('=')[1] || 'video.mp4';
// 创建a标签下载
const dom = document.createElement('a');
dom.href = href;
dom.download = fileName;
dom.style.display = 'none';
document.body.appendChild(dom);
dom.click();
dom.parentNode.removeChild(dom);
window.URL.revokeObjectURL(href);
} catch (err) {
console.log(err)
}
},
3. 捕获异常
由于请求头中限制了响应类型,假如资源不存在或者取流报错,用这种方式接收到的 response 响应体也是 Blob 类型,无法直接读取,需要从 Blob 中读取内容,对以上方法进行修改
async fetchResource(params) {
try {
const res = await Api.streamDownload(params)
const {data, headers} = res || {}
const type = headers['content-type'];
if(type.includes('json')) {
return this.loadErrResp(data).catch(err=>{
err?.code == 11 && this.$message.success('下载失败');
})
}
// 二进制流
const href = window.URL.createObjectURL(new Blob([data]))
const fileName = headers['content-disposition']?.split('=')[1] || 'video.mp4';
// 创建a标签下载
this.downloadResource(href, fileName)
} catch (errBlock) {
console.log(errBlock)
}
},
loadErrResp (data) {
return new Promise((resolve, reject)=>{
const reader = new FileReader()
reader.onload = () => {
const { result } = reader
const errorInfos = JSON.parse(result)
reject(errorInfos)
}
reader.onerror = err => {
reject(err)
}
reader.readAsText(data)
})
},
downloadResource ( href, fileName ) {
const dom = document.createElement('a');
dom.href = href;
dom.download = fileName;
dom.style.display = 'none';
document.body.appendChild(dom);
dom.click();
dom.parentNode.removeChild(dom);
window.URL.revokeObjectURL(href);
},
附base64转文件:
function downloadFileByBase64() {
var fileType = 'pdf';
var base64Str = 'data:application/pdf;base64,*****'
// 前缀
var hasPrefix = base64Str.indexOf('base64,') >= 0;
if (!hasPrefix && !fileType) {
alert('请选择文件后缀');
return false;
}
if (!hasPrefix) {
base64Str = getBase64Type(fileType) + base64Str;
}
var myBlob = dataURLtoBlob(base64Str);
var myUrl = URL.createObjectURL(myBlob);
downloadFile(myUrl, '');
}
// 获取前缀
function getBase64Type(type) {
switch (type) {
case 'txt': return 'data:text/plain;base64,';
case 'doc': return 'data:application/msword;base64,';
case 'docx': return 'data:application/vnd.openxmlformats-officedocument.wordprocessingml.document;base64,';
case 'xls': return 'data:application/vnd.ms-excel;base64,';
case 'xlsx': return 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,';
case 'pdf': return 'data:application/pdf;base64,';
case 'pptx': return 'data:application/vnd.openxmlformats-officedocument.presentationml.presentation;base64,';
case 'ppt': return 'data:application/vnd.ms-powerpoint;base64,';
case 'png': return 'data:image/png;base64,';
case 'jpg': return 'data:image/jpeg;base64,';
case 'gif': return 'data:image/gif;base64,';
case 'svg': return 'data:image/svg+xml;base64,';
case 'ico': return 'data:image/x-icon;base64,';
case 'bmp': return 'data:image/bmp;base64,';
case 'csv': return 'data:text/csv;base64,';
default: return 'data:application/octet-stream;base64,'
}
}
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
function downloadFile(url, name) {
var a = document.createElement("a");
a.setAttribute("href", url);
// 加上这句话可下载
a.setAttribute("download", name)
a.setAttribute("target", "_blank");
let clickEvent = document.createEvent("MouseEvents");
clickEvent.initEvent("click", true, true);
a.dispatchEvent(clickEvent);
}