download

78 阅读1分钟

一、背景

业务中常见下载导出需求,总结了几种常用的。

三种常用方式

(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;
      })
  }