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 浏览器),要么下载的实现由后端接口实现,前端只负责传参和调用