byzhangxinxu from https://www.zhangxinxu.com/WordPress/?p=8016
一, 趁热打铁
上一篇文章也和剪切板粘贴相关, 主要讲的是 输入框粘贴内容的体验优化 , 本文趁热打铁, 继续介绍和剪切板 API 相关的一个交互功能, 当当当当, 就是页面 Ctrl+V 粘贴上传图片.
二, 如何获取剪切板中的图片?
不啰嗦, 直接上代码:
- document.addEventListener('paste', function (event) {
- var items = event.clipboardData && event.clipboardData.items;
- var file = null;
- if (items && items.length) {
- // 检索剪切板 items
- for (var i = 0; i <items.length; i++) {
- if (items[i].type.indexOf('image') !== -1) {
- file = items[i].getAsFile();
- break;
- }
- }
- }
- // 此时 file 就是剪切板中的图片文件
- });
我们在全局 document 对象上绑定一个 paste 粘贴事件, 然后遍历剪切板对象 clipboardData 中的 items , 根据 type 类型确定图片, 并执行 getAsFile() 方法将其转换成二进制的 file 对象, 此 file 对象和 表单中的 file 文件上传 < input > 框 中的 file 对象, 或者拖拽获取的 file 对象是同一个东西.
然后, 我们直接 Ajax 上传这个 file 对象, 上传就成功了, 就这么简单!
三, 如何上传 file 对象?
实际开发, 我们可以借助 FormData 对象进行上传, 示意如下:
- var formData = new FormData();
- formData.append('file', file);
- // 其他些参数, 例如用户 id
- formData.append('userid', 1);
- // Ajax 上传
- var xhr = new XMLHttpRequest();
- // 上传结束
- xhr.onload = function () {
- var JSON = JSON.parse(xhr.responseText);
- // ... 这里处理返回的 JSON 数据
- };
- xhr.open('POST', './upload.PHP', true);
- xhr.send(formData);
如果我们就传一个图片文件, 没有其他乱七八糟数据, 也可以直接 send file 对象, 例如:
- // Ajax 上传
- var xhr = new XMLHttpRequest();
- // 上传结束
- xhr.onload = function () {
- var JSON = JSON.parse(xhr.responseText);
- // ... 这里处理返回的 JSON 数据
- };
- xhr.open('POST', './upload.PHP', true);
- xhr.send(file);
然后 PHP 后台直接 file_get_contents('PHP://input') 获取的就是图片数据了.
三, 如果我想预览剪切板中的图片?
如果上传图片之前, 或者上传过程中想要预览剪切板中的图像怎么办呢? 也很简单, 借助 FileReader 对象, 轻轻松松几行就搞定.
- var reader = new FileReader()
- reader.onload = function(event) {
- // event.target.result 就是图片的 Base64 地址啦
- }
- reader.readAsDataURL(file);
上面代码中的 event.target.result 就是图片的 Base64 地址, 然后页面对应 DOM 元素位置插入如下 html 就可以看到图片效果了:
<img src="'+ event.target.result +'">
四, 实例 demo
您可以狠狠地点击这里: JS 实现页面粘贴图片直接 Ajax 上传 demo
上传演示如下示意:
1. 复制图片
demo 页面提供了图片素材, 我们可以 "右键 - 复制图片", 如下截图:
2. 粘贴图片
Ctrl+V 或者 Commond+V 粘贴. 因为粘贴事件绑定在 document 上, 因此, 只有页面处于 focus 状态, 粘贴既有效果.
3. 预览同时上传
此时, 即触发预览和上传, 不出意外, 应该下面这般模样:
由于本 demo 图片上传保存的最终图片均是用的剪切板中默认的同一个文件名, 因此, 如果多人同时上传, 可能会出现被覆盖的情况, 实际开发显然需要重命名哦.
本功能只能上传剪切板中的图片
本功能只能上传剪切板中的图片.
当我们使用 QQ 或者公司内部聊天工具中的截图工具截屏的时候, 剪切板中是有截屏图片的;
当我们在任意网页中的图片上 "右键 - 复制图片", 也是在剪切板中.
但是, 但是, 但是, 我们在操作系统的文件夹中复制图片, 不好意思, 这个图片并不是在剪切板中, 因此, 无法上传.
这是个可能会让人困扰的地方. 在 Windows 文件夹系统中, 我们复制文本类的东西, 是在剪切板中, 我们可以获得之; 但是, 复制的图片文件, 不论是右键复制, 还是 Ctrl + C 复制都不行. 我曾经尝试找过 "右键 - 复制到剪切板" 这样的小工具, 以便提高我们后台编辑人员的工作效率, 失败了, 如果谁知道有这样的工具, 欢迎指教.
因此, 桌面系统中的图片, 目前实践下来, 比较便捷的还是拖拽上传, 以及文件选择框多选上传 (demo 参见这里).
五, 兼容性与渐进增强
自己测试了下, Chrome 和 Firefox 浏览器都是 OK 的, Safari 还没有测试, 经验来看, 应该没问题. 关于是 IE 浏览器, 并不支持.
首先, paste 事件必须在 contenteditable 的元素中才能执行, 然后 get 不到 clipboardData 中的 items , 所以, 放弃 IE 即可!
本身, 剪切板直接上传图片就是一个渐进增强的功能.
实际开发是这样的:
<input type="file"> 上传是必备; 拖拽上传是标配; 粘贴上传则是 VIP 服务, 锦上添花的事情, 有更好, 没有也只是和以前一样.
因此, 所有用到图片上传的地方, 我们都可以直接大胆多一个剪切板上传功能, 韩信将兵多多益善. 而且 Ajax 上传这些都是重复利用的, 实际就多了一点点代码量, 性价比很高.
目前实际产品开发中用的比较多的是富文本编辑器中, 例如知乎的文章编辑器, 剪切板图片直接复制就可以上传:
看上去很高级, 看了本文是不是觉得原来其实很简单, 对吧.
好的体验有时候并不需要多么高深的技术, 一个小小的技术 tips 足矣!
六, 结束语
以前图片示例都使用张含韵, 我这样的小站用用其实也不会有啥. 不过我家领导比较胆小谨慎, 老担心万一张含韵告我侵犯版权, 到时候, 卖房子都赔不起. 我和我家领导在做决定的时候一向公平公正, 意见相同的时候听我的, 意见不同的时候听领导的. 所以, 这次, 我就听了领导的话, 张含韵所有图片下架, 于是, 数百篇文章, 那是一篇一篇的过, 所以版权图片全部替换掉 (很多需要重新截图), 花了我足足几个星期的业余时间.
然后顶替上来的图片是下面这位:
名叫吴板泉, 用了一段时间, 结果那是反响平平, 不对, 是什么响都没有.
我琢磨了下, 一定是年纪偏大, 太熟了, 而且还带了个装逼的墨镜是什么鬼! 觉得必须得重新换图, 于是, 迎来了下面这位, 叮叮叮叮:
这位小美女名叫陈晨玲, 常用昵称是 CC0, 怎么样? 是不是看上去很有心动的感觉.
来源: http://www.tuicool.com/articles/e2YNNfF