概述
前景
在项目开发中,发现通过增加a
标签的download
属性来下载文件,如果是图片会直接跳转不会下载,所以通过js去实现下载
兼容
由于项目本身使用的是vue,所以不支持ie9以下的,而ie9以上的都支持对应的api
但是考虑到不是vue的,所以还是用原生的写法,改成vue也好改嘛
具体实现
场景1(先预览,再下载)
- html
如果图片的地址和当前不同源,则需要加上crossorigin="anonymous"
属性;
如果同源,则可以不加上(ps: 减少代码)
<div id="imgBox">
<img id="image" src="xxx" crossorigin="anonymous">
</div>
- js
直接读取img
标签生成的图片,可以避免二次下载,但是需要图片加载完成才能去点击下载,不然会下载不完整
const img = document.querySelector('#image');
// 下载功能
function downlaod () {
let canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const img = document.querySelector('#image');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight);
canvas.toDataURL('image/jpeg', 1);
let dataUrl = canvas.toDataURL();
let aObj = document.createElement('a');
aObj.download = demo.jpeg;
aObj.href = dataUrl;
aObj.click();
// 清除缓存,释放空间
dataUrl = null;
aObj = null;
canvas = null;
}
// 这里是确保图片加载完成
img.onload = () => {
const imgBox = document.querySelector('#imgBox');
const button = document.createElement('button');
button.onclick = (e) => {
if (e && e.preventDefault) {
e.preventDefault();
}
download();
}
button.innerHtml = '下载';
imgBox.appendChild(button);
};
场景2(直接下载)
- html
<button id="download">下载</button>
- js
这样的好处是随时点随时下载,不需要等图片加载完再去点
const btn = document.querySelector('#download');
btn.onclick = (e) => {
if (e && e.preventDefault) {
e.preventDefault();
}
let img = new Image();
img.src = 'xxxx';
img.crossorigin = 'anonymous';
img.onload = () => {
let canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight);
canvas.toDataURL('image/jpeg', 1);
let dataUrl = canvas.toDataURL();
let aObj = document.createElement('a');
aObj.download = options.name;
aObj.href = dataUrl;
aObj.click();
dataUrl = null;
aObj = null;
canvas = null;
img = null;
}
}
注意: 上面两种方式,最好都加个防抖动处理
网友评论