JavaScript 纯前端实现图片的上传、下载与复制
这次在写一个画布应用,由于是纯前端的项目(我也希望加入后端啊可是后端在公司里申请机器要走架构评审),所以和普通的上传到服务器不太一样,下载倒是比较常见的函数,复制也是新增研究对象……当然大家懂得,博客第一段通常是用来吐槽的……所以这是一篇吐槽文。
从最简单的开始——下载
下载之所以说是最简单的,是因为它是在太常用了!创造一个 a
标签并且模拟点击,使用 canvas.toDataURL
把 URI 写入,然后在需要的位置调用这个函数就能起到下载的效果,完全没毛病(大概就是用 a
标签引用文件地址点击能下载那么简单的原理)。原理说起来挺简单的,实际上用到的比如模拟点击,平时确实不是很常用,不过还好,需求比较特殊,当个 copy-paste 工程师也没什么不好。
const downloadImage = function(canvas) {
const image = canvas.toDataURL('image/png')
const dLink = document.createElement('a')
const evt = new MouseEvent('click')
dLink.download = 'image.png'
dLink.href = image
dLink.dispatchEvent(evt)
}
上传图片
正常我们的上传都是对应的一个接口,然后用 form-data
的形式把内容传入,无论是普通的上传方式还是流式上传(大文件上传时比较实用,当然最好还是断点),实际上都对应了服务器端——Emmm,从来没有做过一个纯前端还有上传需求的业务呢。
不过只要 so 一下,就能发现还是可以做的。
在这里我们主要用到的是 FileReader
对象,它可以读取你的文件并且处理成数据流的形式:https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader
可以读取为 DATAURL,那么就能载入到 canvas 中了:
const uploadImage = function(upload, cb) {
const reader = new FileReader()
if (upload) {
reader.readAsDataURL(upload.files[0])
}
reader.addEventListener('load', () => {
const img = new Image()
img.src = reader.result
img.onload = () => {
cb(reader, img)
}
})
}
复制图片
复制图片一开始其实我也有点怀疑,真的可以做到吗,从原理上就是把数据写入剪贴板,唯一的问题是:到底给不给你写图片的权限,之前实际上做过写文字,第一是使用开源库,第二是使用一个 execCommand
方法。
后来其实找到了这样一个方法:https://developer.mozilla.org/zh-CN/docs/Web/API/ClipboardEvent/clipboardData
const copyToClipboard = function(canvas, e) {
const image = canvas.toDataURL('image/png')
e.clipboardData.setData('image/png', image)
e.preventDefault()
}
实现大概是以上,但是会发现并不能生效。
主要是因为 image/png
并不在 Chrome 的支持范围内,其实这是一个 Chrome 的 bug(或许也许也成为了 feature?)依旧是很多年都没有修:
https://bugs.chromium.org/p/chromium/issues/detail?id=150835
如果使用 Firefox 之类的浏览器,是可以这么做的。
植入部分
如果您觉得文章不错,可以通过赞助支持我。
如果您不希望打赏,也可以通过关闭广告屏蔽插件的形式帮助网站运作。
这样子刷新页面后还能显示吗?
上传吗?不能
支持IE吗?