581 字
3 分钟
实现图片下载的常用方法
后端配合下载
TIP 需要下载的图片是后端生成并返回的场景。
设置返回的响应数据类型 responseType: ‘blob’
export const exportPNG = async (token?: string, id?: string, height?: string) => {
// ...
const pngData = await getPNGAsync(params);
if (pngData.status) {
ElMessage.warning('下载失败,请尝试重新导出');
return;
} else {
const blob = new Blob([pngData], { type: 'application/image' });
const downloadElement = document.createElement('a');
const href = window.URL.createObjectURL(blob); //创建下载的链接
downloadElement.href = href;
downloadElement.download = `${fileName}.png`; //下载后的文件名,根据需求定义
document.body.appendChild(downloadElement);
downloadElement.click(); //点击下载
document.body.removeChild(downloadElement); //下载完成移除元素
window.URL.revokeObjectURL(href); //释放掉blob对象
}
};
纯前端下载
TIP 需要下载的图片是,本地页面的图片或者一个图片的URL的场景
同源的图片
TIP 同源的图片可以直接利用a标签进行下载,给a标签设置
download
(H5
新增的属性)属性可以:指定下载后的文件名称,并告诉浏览器下载该URL,而不是访问其指向的内容
<img src="./axios.png" alt="" style="height: 200px;" >
<a href="./axios.png" download="axios.png" target="_blank">点击下载</a>
非同源的图片
TIP 跨域的图片不能直接使用a标签下载,可通过以下几种方式:
1. 利用canvas
TIP 因为Base64编码不受同源策略限制,所以可以利用canvas的
toDataURL
API得到图片的Base64编码,然后再利用a标签设置download属性下载
const downloadImage = (imgUrl) => {
const image = new Image()
const fileName = imgUrl && imgUrl.split('/').pop() // 文件名
// 解决跨域 Canvas 污染问题
image.setAttribute('crossOrigin', 'anonymous');
image.onload = function(e) {
const canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
const context = canvas.getContext('2d')
context.drawImage(image,0,0,image.width,image.height)
// 得到图片的Base64编码数据
const url = canvas.toDataURL('image/png')
const a = document.createElement('a')
const event = new MouseEvent('click')
a.download = fileName || 'img'
a.href = url
a.dispatchEvent(event)
}
image.src = imgUrl
}
WARNING 需要注意的是,图片加载时异步的,在转化成dataURL前必须先确保图片加载到,否则让canvas立即执行绘制可能失败,所以我们应该把绘制canvas和转换Base64编码的过程放在onload中
2. 创建XHR对象发起请求
const downloadIamge2 = (imgUrl) => {
event.returnValue = false; // 阻止默认事件
const x = new XMLHttpRequest();
x.open("GET", imgUrl, true);
x.responseType = 'blob'; // 设置响应类型
const fileName = imgUrl && imgUrl.split('/').pop() // 文件名
x.onload = function (e) {
const url = window.URL.createObjectURL(x.response)
const a = document.createElement('a');
a.href = url
a.download = fileName || 'img'
a.click()
}
x.send();
}