Skip to content
文章目录

a标签download属性无效

如何看当前浏览器的 a 标签是否支持 download 属性

ts
const isSupportDownload = 'download' in document.createElement('a')
console.log(isSupportDownload)

原因

  • download 可以实现对下载文件的重新命名,但是存在一定的兼容问题,需要到 can i use 看兼容情况
  • 在 HTML5 中,A 标签是支持 download 属性的,此属性指示浏览器下载 URL 而不是导航到它,但是该属性受到同源策略的限制
  • 下载文件不是在子集的服务器域名中,浏览器会忽略 download 属性,即跨域会导致 download 属性无效

如:

html
<a download="课程附件.pdf " href="http://api.bluemoon.com.cn/课程.pdf">test</a>

如果你的系统的访问域名不是http://api.bluemoon.com.cn,download 就会无效

又如:

html
<a href="http://192.168.1.102/abc.xlsx" download="abc.xlsx">下载</a>

这种写法有个前提:href 的下载地址 和 当前网站地址 必须是 同源的,否则 download 不生效。

js
const width = 200,
  height = 200

// 创建canvas
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
canvas.width = width
canvas.height = height

// 创建Image实例
const img = new Image()
img.setAttribute('crossOrigin', 'Anonymous')
img.src = url

img.onload = function () {
  context.drawImage(img, 0, 0, width, height)
  const a = document.createElement('a')
  a.href = canvas.toDataURL()
  a.download = name
  a.click()
}

解决方案

  • 非图片文件,可以通过 js 实现文件下载
  • 图片文件,则可以将图片内容画到 canvas 中(注意: 此时这个图片一定要开启跨域支持),然后通过 canvas 获取图片的 base64 编码,再通过超链接的 download 属性下载这个 base64 编码

通过后端将图片转换为 blob

ts
changeDataType(url) {
    return fetch(url).then((response) => {
      return response.blob();
    }).then(blob => {
      return URL.createObjectURL(blob);
    });
}

异步执行上述方法将其下载

ts
async download(originURL) {
    const a = document.createElement('a');
    a.href = await this.changeDataType(originURL);
    a.download = '';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
}

特殊情况

某些浏览器 a 标签支持download 属性, 但实际效果却没反应. 如:某些品牌平板的默认浏览器(如:OPPO 平板自带浏览器),原因要么是因为没有给浏览器授予存储权限,要么是因为品牌商替换了浏览器的默认下载实现。此时的解决方案就只有两种方式,要么让用户换成纯净的浏览器(如:原生的 chrome 浏览器或 edge 浏览器),要么下载的实现由后端接口实现,前端只负责传参和调用

参考资料

浅析 HTML5 中的 download 属性

使用了 HTML a 标签中的 download 属性,却出现了意外

a 链接 download 不生效问题

a 标签下载文件重命名失败,download 无效解决方案

a 标签设置下载文件名无效解决方法

了解 HTML/HTML5 中的 download 属性