前言
自从openai开放gpt之后,网上各种AI产品层出不穷,AI生成文本、图片都是主要其功能,图片生成以后那么复制和下载自然而然也就是必备功能,否则生成之后不能复制不能下载就显得没什么用了。
图片复制
前端复制用的最多的就是documnet.execCommand和Clipboard
- 使用document.execCommand
const range = document.createRange();
range.selectNode(image);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
从官方文档可以看到
documnet.execCommand已经被弃用了,而且该方法是用来操纵可编辑内容区域的元素,从上面的代码也可以看出执行命令时需要先进行选中,如果图片不可编辑,无法选中也就没办法进行复制。
- Clipboard,直接上代码
const img = new Image();
img.crossOrigin = 'anonymous';
img.src = "imageUrl";
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d')!;
ctx.drawImage(img, 0, 0);
canvas.toBlob((blob) => {
const item = new ClipboardItem({ 'image/png': data });
navigator.clipboard
.write([item])
.then((res) => {
console.log('复制成功', res);
})
.catch((err) => {
console.log('复制失败', err);
});
});
}
代码很简单,就是创建一个image对象,然后加载图片的url,加载成功后我们就可以拿到图片的信息,然后使用canvas绘制转为Blob,再使用Clipboard将数据写入剪切板。 需要注意的是:
image必须设置属性crossOrigin,否则canvas绘制的时候就会报下面的错误:
错误原因就是因为图片资源跨域了,导致canvas画布污染
官方也给出了解释,在canvas中使用其他来源的图片会被认为是不安全的,元素本身调用toBlob方法也会抛出异常,所以我们需要添加
crossOrigin属性
想要在canvas中使用必须使用CORS。
2. 使用
clipboard剪切板的时候只能是png格式(具体什么原因还不清楚,也没有查到相关资料,有知道的人可以敲下让我也学习一番)
图片下载至本地
图片下载如果是纯web项目可以直接a标签链接图片下载地址使用浏览器下载,这个下载路径就是浏览器的下载路径,不能让用户单独选择下载路径,如果下载的时候想让用户选择路径,那么就需要其他办法了。
- download属性
let link = document.createElement('a');
link.href = "imageUrl";
link.download = `image.${ext}`;
link.click();
download属性存在兼容性问题,只有chrome和Firefox支持,而且只在同源 URL 或 blob:、data: 协议起作用。但是图片大多是放在cdn上面的,那么这里就只能考虑使用blob或者data。粘贴的时候我们就已经展示了将图片转为blob,这里用同样的方法将图片转为data
const img = new Image();
img.crossOrigin = 'anonymous';
img.src = url;
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d')!;
ctx.drawImage(img, 0, 0);
let ext = img.src.substring(img.src.lastIndexOf('.') + 1).toLowerCase();
let dataURL = canvas.toDataURL('image/' + ext);
};
至此就已经完成了使用download属性下载的功能。
- 如果是使用electron开发桌面端的话,我们还可以使用electron中的
showSaveDialog完成保存本地,代码如下
dialog.showSaveDialog({ showsTagField: false, defaultPath: 'image.png' })
.then((res) => {
const path = res.filePath;
fetch("imageUrl").then(response => {
response.arrayBuffer().then(res => {
writeFile(path, Buffer.from(res), (err) => {
console.log(err);
});
});
});
});
主要就是利用showSaveDialog进行文件夹选择,然后通过nodejs的fs模块中的writeFile将数据写入文件。