CodeSky 代码之空

随手记录自己的学习过程

JavaScript 纯前端实现图片的上传、下载与复制

2018-05-11 19:53分类: JavaScript评论: 3

这次在写一个画布应用,由于是纯前端的项目(我也希望加入后端啊可是后端在公司里申请机器要走架构评审),所以和普通的上传到服务器不太一样,下载倒是比较常见的函数,复制也是新增研究对象……当然大家懂得,博客第一段通常是用来吐槽的……所以这是一篇吐槽文。

从最简单的开始——下载

下载之所以说是最简单的,是因为它是在太常用了!创造一个 a 标签并且模拟点击,使用 canvas.toDataURL 把 URI 写入,然后在需要的位置调用这个函数就能起到下载的效果,完全没毛病(大概就是用 a 标签引用文件地址点击能下载那么简单的原理)。原理说起来挺简单的,实际上用到的比如模拟点击,平时确实不是很常用,不过还好,需求比较特殊,当个 copy-paste 工程师也没什么不好。

1const downloadImage = function(canvas) {
2  const image = canvas.toDataURL('image/png')
3  const dLink = document.createElement('a')
4  const evt = new MouseEvent('click')
5  dLink.download = 'image.png'
6  dLink.href = image
7  dLink.dispatchEvent(evt)
8}
9

上传图片

正常我们的上传都是对应的一个接口,然后用 form-data 的形式把内容传入,无论是普通的上传方式还是流式上传(大文件上传时比较实用,当然最好还是断点),实际上都对应了服务器端——Emmm,从来没有做过一个纯前端还有上传需求的业务呢。

不过只要 so 一下,就能发现还是可以做的。

在这里我们主要用到的是 FileReader 对象,它可以读取你的文件并且处理成数据流的形式:https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader

可以读取为 DATAURL,那么就能载入到 canvas 中了:

1const uploadImage = function(upload, cb) {
2  const reader = new FileReader()
3  if (upload) {
4    reader.readAsDataURL(upload.files[0])
5  }
6
7  reader.addEventListener('load', () => {
8    const img = new Image()
9    img.src = reader.result
10    img.onload = () => {
11      cb(reader, img)
12    }
13  })
14}
15

复制图片

复制图片一开始其实我也有点怀疑,真的可以做到吗,从原理上就是把数据写入剪贴板,唯一的问题是:到底给不给你写图片的权限,之前实际上做过写文字,第一是使用开源库,第二是使用一个 execCommand 方法。

后来其实找到了这样一个方法:https://developer.mozilla.org/zh-CN/docs/Web/API/ClipboardEvent/clipboardData

1const copyToClipboard = function(canvas, e) {
2  const image = canvas.toDataURL('image/png')
3  e.clipboardData.setData('image/png', image)
4  e.preventDefault()
5}
6

实现大概是以上,但是会发现并不能生效。

主要是因为 image/png 并不在 Chrome 的支持范围内,其实这是一个 Chrome 的 bug(或许也许也成为了 feature?)依旧是很多年都没有修:

https://bugs.chromium.org/p/chromium/issues/detail?id=150835

如果使用 Firefox 之类的浏览器,是可以这么做的。

评论 (2)

fls2018年7月18日 10:00

支持IE吗?

hellolex2018年5月17日 12:47

这样子刷新页面后还能显示吗?

敖天羽2018年5月17日 12:48

上传吗?不能