当前位置:   article > 正文

简单的聊一聊如何使用标签下载文件

a标签下载

2371f330a5cde74ccfe2ce14a949baa4.jpeg

前言

6a7fbeea70c88e553f3f09ae8251348c.png

最近和后端联调下载时忽然发现屡试不爽的 标签下载失灵了?这才感觉自己对文件下载一直处在一知半解的模糊状态中,趁端午前夕有空赶紧总结了一下,和大家一起讨论讨论。

标签 download

这应该是最常见,最受广大人民群众喜闻乐见的一种下载方式了,搭配上 download 属性, 就能让浏览器将链接的 URL 视为下载资源,而不是导航到该资源。

如果 download 再指定个 filename ,那么就可以在下载文件时,将其作为预填充的文件名。不过名字中的 / 和 `` 会被转化为下划线 _,而且文件系统可能会阻止文件名中的一些字符,因此浏览器会在必要时适当调整文件名。

封装下载方法

贴份儿我常用的下载方法:

  1. ts
  2. 复制代码
  3. const downloadByUrl = (url: string, filename: string) => {
  4.     if (!url) throw new Error('当前没有下载链接');
  5.     const a = document.createElement("a");
  6.     a.style.display = "none";
  7.     a.href = url;
  8.     a.download = filename;
  9.     // 使用target="_blank"时,添加rel="noopener noreferrer" 堵住钓鱼安全漏洞 防止新页面window指向之前的页面
  10.     a.rel = "noopener noreferrer";
  11.     document.body.append(a);
  12.     a.click();
  13.     setTimeout(() => {
  14.         a.remove();
  15.     }, 1000);
  16. };
Firefox 不能一次点击多次下载

这里有个兼容性问题:在火狐浏览器中,当一个按钮同时下载多个文件(调用多次)时,只能下载第一个文件。所以,我们可以利用 标签的 target 属性,将其设置成 _blank 让火狐在一个新标签页中继续下载。

  1. ts
  2. 复制代码
  3. // 检查浏览器型号和版本
  4. const useBrowser = () => {
  5.     const ua = navigator.userAgent.toLowerCase();
  6.     const re = /(msie|firefox|chrome|opera|version).*?([\d.]+)/;
  7.     const m = ua.match(re);
  8.     const Sys = {
  9.         browser: m[1].replace(/version/, "'safari"),
  10.         version: m[2]
  11.     };
  12.     return Sys;
  13. };

添加一个浏览器判断:

  1. ts
  2. 复制代码
  3. const downloadByUrl = (url: string, filename: string) => {
  4.     // 略......
  5.     //  火狐兼容
  6.     if (useBrowser().browser === "firefox") {
  7.         a.target = "_blank";
  8.     }
  9.     document.body.append(a);
  10. }

download 使用注意点

标签虽好,但还有一些值得注意的点:

1. 同源 URL 的限制

download 只在同源 URL 或 blob: 、 data: 协议起作用

也就是说跨域是下载不了的......

首先,非同源 URL 会进行导航操作。其次,如果非要下载,那么正如上面的文档所说,可以先将其转换为 blob: 或 data: 再进行下载,至于如何转换会在 Blob 章节中详细介绍。

2. 无法鉴权

使用 标签下载是带不了 Header 的,因此也不能携带登录态,所以无法进行鉴权。这里我们给出一个解决方案:

  1. 先发送请求获取 blob 文件流,这样就能在请求时进行鉴权;

  2. 鉴权通过后再执行下载操作。

这样是不是就能很好的同时解决问题1和问题2带来的两个痛点了呢

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/63606
推荐阅读
相关标签