需求描述
今天我这边有个需求是做一个简易素材上传管理的业务模块,想要满足用户复制图片到剪切板中,能够在我的页面中直接粘贴上传
实现方式
普遍采用的方式就是来监听paste事件,来获取剪切板里的文件
还有一种方式就是采用一个比较新的Clipboard API,这个需要通过用户同意之后,才可以使用
我试了一下,写法相对舒适一些,read方法会直接返回一个Promise,不过可能因为还比较新,支持性很不好,在Chrome里读取字符串没问题,读文件会返回一个ClipboardItem,没有找到解析的方式。。
document.addEventListener('paste', (e) => {
const cbd = e.clipboardData
for (let i = 0; i < cbd.items.length; i++) {
const item = cbd.items[i]
if (item.kind === 'file') {
const blob = item.getAsFile()
if (!blob || blob.size === 0) {
return
}
}
}
}, false)
发现问题
其中发现个问题,我复制了个2M的jpg图片,通过页面粘贴之后我输出了下文件大小,变成了12M多!
经过各种Google,也没有一个完全准确的解释,不过我猜测的话不是mac对复制到剪切板做了处理就是浏览器做了处理。我切换了不同的浏览器,发现文件大小果真不一样,所以我认为就是每个浏览器对剪切板中的文件都做了处理,而且发现blob中的文件类型是png,我上传的可是jpg啊!我又试了下png,文件大小的变化不大。
解决问题
既然被搞大了,肯定是要解决的。思路的话,转成base64肯定会更大了,我在想前端压缩一下吧,前端压缩的方式也就是用canvas了;我压缩了之后发现效果并不理想,质量设置太低了的话又容易失真。
后来我又想到把图片再转回成jpg的格式试一下,结果很惊喜,文件大小又回到了2M左右
不过我粘贴的时候已经被处理成png了,所以说我并不知道这个图片之前是什么格式的,也不能一股脑儿的都转成jpg,这样也不合理。
我又研究了下clipboardData里面的数据,发现items里面是有两条数据的,一个是file,一个是string,我在想这个string是不是就是文件名,又google一下,发现了getAsString这个方法,我获取了一下stringed内容,果然是文件的真实名字,这样图片的的真正格式就能取到了。
done!


第一张就是2M的jpg,第二张是860k的png,差距还是很大的
最后
目前还有两个功能没有找到实现的方法,一个是我在初始化的时候想要自动去读取剪切板里的图片,我用了document.execCommand('paste'),但实际上并没有触发;还有就是怎么做到一次性粘贴多张图片
这两个我还没有找到解决方法,欢迎大佬指路