一、背景
业务中常见下载导出需求,总结了几种常用的。
三种常用方式
(1)页面重定向
原理:通过 location.href = $url ,将当前页面重定向一个传递流的 url,浏览器检测到传输的 mime-type 为可下载的类型后,会唤起下载操作。
function downloadByHref(url) {
localtion.href = url;
}
或
function downloadByHref(url) {
window.open(url)
}
特点: 代码简单易懂,比较粗糙,在本地测试时会跑到 localhost 下。
(2)创建iframe
原理:通过新建一个 iframe 将 iframe 的 src 指向一个『 流 』,同样可以唤起浏览器的下载窗口。
function downloadByIframe(url) {
const iframe = document.createElement('iframe');
document.querySelector("body").appendChild(iframe);
iframe.style = { display: 'none' };
iframe.src = `${localtion.origin}${url}`;
setTimeout(() => {
document.querySelector("body").removeChild(iframe);
}, 1000);
}
(3)创建 a 标签
原理:借助 a.download 属性,借助 blob 对象,使用 dataUrl 下载。
优点:即使不是流也可以下载,并可以自己设置下载文件名。
不足:1.手机端不支持!!!2.需要前后端统一对 header 做 utf-8 编解码。
// utf-8 转 文字
decodeUtf8 = (bytes) => {
let encoded = '';
for (let i = 0; i < bytes.length; i++) {
encoded += bytes[i].toString(16);
}
return decodeURIComponent(encoded);
}
function downloadStatic(url, params, fileName) {
fetch(url, { method: 'POST', body: JSON.stringify(params) }).then(async res => {
let beFileName = decodeUtf8(res.headers.get('content-disposition').split('=')[1]);
const blob = await res.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
// 配置下载文件的属性
a.download = beFileName || fileName || 'download';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
})
.catch(e => {
throw e;
})
}