简介:主要介绍web前端下载图片的几种方式及具体实现代码
最近开发一个AI图片生成的客户端时发现以前用过的js下载图片(base64格式)居然不管用了,具体原因不明。在网上也找了很多资料,下载图片的js代码和我的js代码大同小异。
网上下载图片的代码一:
// 生成一个a元素
var a = document.createElement("a");
// 创建一个单击事件
var event = new MouseEvent("click");
// 设置图片名称
a.download = "photo"+(new Date()).getTime();
// 将生成的URL设置为a.href属性
a.href = url;
// 触发a的单击事件
a.dispatchEvent(event);
网上类似代码二:
// 生成一个a元素并将a标签添加到页面上
var a = document.createElement("a");
document.body.appendChild(a);
// 设置图片名称
a.download = "photo"+(new Date()).getTime();
// 将生成的URL设置为a.href属性
a.href = url;
// 触发a标签的单击事件
a.click();
//清除缓存信息并删除页面上的a标签
window.URL.revokeObjectURL(a.href);
document.body.removeChild(a);
上述两种方法其实都是同一种原理,将图片的url赋值给a标签,然后模拟a标签的点击事件,调取下载功能。最后实验发现,确实能调起下载弹窗,但是无法下载。
反思了一下,突然想到我的AI服务器返回给我的是base64格式的图片,将base64格式的图片当成url复制给a标签的url。可能出错的就是这一步,于是我将base64转换成blob,再将blob转换成DOMString,最后由DOMString去触发下载事件。
我的最总代码如下所示:
import { Toast } from 'vant';
//获取手机型号
function isWechatClient(){
var ua = navigator.userAgent.toLowerCase();
return ua.indexOf('micromessenger')!=-1
}
//将base64转换为blob
function dataURLtoBlob(dataurl) {
//判断是否为微信
var arr = dataurl.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
}
function downloadFile(url, name = "photo") {
if (isWechatClient()) {
Toast('请长按下载图片,或者使用其他浏览器打开下载');
//或者对接微信公众号的jssdk
return;
}
var a = document.createElement("a");
a.setAttribute("href", url);
a.setAttribute("download", name+(new Date()).getTime());
a.setAttribute("target", "_blank");
let clickEvent = document.createEvent("MouseEvents");
clickEvent.initEvent("click", true, true);
a.dispatchEvent(clickEvent);
}
function downloadBase64Img(base64) {
var myBlob = dataURLtoBlob(base64);
var myUrl = URL.createObjectURL(myBlob);
return downloadFile(myUrl);
}
注意:由于微信端(或者钉钉)无法通过js下载图片,要想在前端下载图片必须对接微信公众号的jssdk。所以在上述代码中我判断了是否为微信端,如果是微信端提示用户长按下载图片或者使用其他浏览器打开下载。
虽然上述代码可以下载图片,不过有些手机可能打开了云存储功能,下载的图片会直接保存在云空间。如果你的手机相册没有下载的图片可以去云空间(例如:iOS的iCloud)查看。
有遗漏或者不对的可以在我的公众号留言哦