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 之类的浏览器,是可以这么做的。

如果您觉得文章不错,可以通过赞助支持我

标签: 知识, 代码段, 语法

已有 2 条评论

  1. hellolex

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

添加新评论