用Ubuntu两年多了,习惯了Ubuntu的操作感觉比WIN用起来还爽,就一点不爽,生态应用很少,好多WIN上好用的软件在Ubuntu找不到的,希望以后的软件可以做到一次编译全平台通用. 即使用上Wine有的软件应用也存在兼容性问题.比如QQ,Photoshop,微信,旺旺.
所以,在Ubuntu使用过程中,习惯了用web来访问,凡事web-Application通通喜欢.
微信和钉钉经常用,不喜欢wine安装的应用,就直接网页版微信,网页版钉钉,发现好YI功能,当我截图复制到剪贴板后,可以直接Ctrl+V在网页版微信,钉钉粘贴,不用在把图片先保存在电脑上,再选择发送文件这么复杂.
然后呢,命题就出来了,如何做到从剪贴板获取图片并发送图片呢?
paste剪贴板事件
onpaste 事件在用户向元素中粘贴文本时触发。
有三种方式可以在元素中粘贴内容:
- 按下 CTRL + V
- 从浏览器的编辑菜单中选择 "Paste(粘贴)"
- 右击鼠标按钮在上下文菜单中选择 "Paste(粘贴)" 命令
参考:https://www.w3cschool.cn/jsref/event-onpaste.html
绑定的元素不一定是input,普通的div也是可以绑定的,如果是给document绑定了,就相当于全局了,任何时候的粘贴操作都会触发。
粘贴事件提供了一个clipboardData的属性,如果该属性有items属性,那么就可以查看items
中是否有图片类型的数据了。
clipboardData介绍
介绍一下clipboardData对象,它实际上是一个DataTransfer类型的对象,DataTransfer是拖动产生的一个对象,但实际上粘贴事件也是它。
clipboardData的属性介绍
属性 | 类型 | 说明 |
---|---|---|
dropEffect | String | 默认是 none |
effectAllowed | String | 默认是 uninitialized |
files | FileList | 粘贴操作为空List |
items | DataTransferItemList | 剪切板中的各项数据 |
types | Array | 剪切板中的数据类型 该属性在Safari下比较混乱 |
items
介绍
items
是一个DataTransferItemList
对象,自然里面都是DataTransferItem
类型的数据了。
items
属性
items
的DataTransferItem
有两个属性kind
和type
属性 | 说明 |
---|---|
kind | 一般为string 或者file |
type | 具体的数据类型,例如具体是哪种类型字符串或者哪种类型的文件,即MIME-Type |
items
方法
方法 | 参数 | 说明 |
---|---|---|
getAsFile | 空 | 如果kind 是file ,可以用该方法获取到文件 |
getAsString | 回调函数 | 如果kind 是string ,可以用该方法获取到字符串,字符串需要用回调函数得到,回调函数的第一个参数就是剪切板中的字符串 |
types
介绍
一般types
中常见的值有
值 | 说明 |
---|---|
text/plain | 普通字符串 |
text/html | 带有样式的html |
Files | 文件(例如剪切板中的数据) |
以上介绍COPY来自: https://www.jb51.net/article/123071.htm
FileReader对象
FileReader
对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File
或 Blob
对象指定要读取的文件或数据。其中File对象可以是来自用户在一个<input>
元素上选择文件后返回的FileList
对象,也可以来自拖放操作生成的 DataTransfer
对象,还可以是来自在一个HTMLCanvasElement
上执行mozGetAsFile()
方法后返回结果。
事件处理
FileReader.onload
处理load
事件。该事件在读取操作完成时触发。
FileReader.onloadend
处理loadend
事件。该事件在读取操作结束时(要么成功,要么失败)触发。
方法
FileReader.readAsDataURL()
开始读取指定的Blob
中的内容。一旦完成,result
属性中将包含一个data:
URL格式的字符串以表示所读取文件的内容。
readAsDataURL: 该方法会读取指定的 Blob
或 File
对象。读取操作完成的时候,readyState
会变成已完成(DONE),并触发 loadend
事件,同时 result
属性将包含一个data:
URL格式的字符串(base64编码)以表示所读取文件的内容。
示例: https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader/readAsDataURL
function previewFile() { var preview = document.querySelector('img'); var file = document.querySelector('input[type=file]').files[0]; var reader = new FileReader(); reader.addEventListener("load", function () { preview.src = reader.result; }, false); if (file) { reader.readAsDataURL(file); } }
来自:https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader
base64数据转blob二进制
请看昨日文章:
JS 实现blob与base64互转
/** * base64 to blob二进制 */ function dataURItoBlob(dataURI) { var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; // mime类型 var byteString = atob(dataURI.split(',')[1]); //base64 解码 var arrayBuffer = new ArrayBuffer(byteString.length); //创建缓冲数组 var intArray = new Uint8Array(arrayBuffer); //创建视图 for (var i = 0; i < byteString.length; i++) { intArray[i] = byteString.charCodeAt(i); } return new Blob([intArray], {type: mimeString}); }
呈上仿制代码
ok,以上需要的事件, FileReader对象操作,base64数据转换都有了,那我们就直接上代码.
ImageClipboard.html
<div id="box"></div> <script type="text/javascript"> // window.addEventListener('paste', pasteHandler); pasteHandler= fun... window.addEventListener('paste', function (e) { var items; if (e.clipboardData && e.clipboardData.items) { items = e.clipboardData.items; if (items) { items = Array.prototype.filter.call(items, function (element) { return element.type.indexOf("image") >= 0; }); Array.prototype.forEach.call(items, function (item) { var blob = item.getAsFile(); var reader = new FileReader(); reader.onloadend = function (event) { var imgBase64 = event.target.result; // event.target.result.split(",") [0]=data:image/png;base64 [1]=data console.log(imgBase64); // base64 var dataURI = imgBase64; var blob = dataURItoBlob(dataURI); // blob console.log(blob); uploadImg(blob); }; reader.readAsDataURL(blob); }); } } }); /** * base64 to blob二进制 */ function dataURItoBlob(dataURI) { var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; // mime类型 var byteString = atob(dataURI.split(',')[1]); //base64 解码 var arrayBuffer = new ArrayBuffer(byteString.length); //创建缓冲数组 var intArray = new Uint8Array(arrayBuffer); //创建视图 for (var i = 0; i < byteString.length; i++) { intArray[i] = byteString.charCodeAt(i); } return new Blob([intArray], {type: mimeString}); } /** * 上传图片 FormData */ function uploadImg(file) { var formData = new FormData(); formData.append('my-image-file', file); formData.append('username', 'myfile'); // 添加自定义数据 var xhr = new XMLHttpRequest(); xhr.open('POST', '/html/upload-ser.php'); xhr.onload = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { var data = JSON.parse(xhr.responseText), tarBox = document.getElementById('box'); if (data.id == 1) { var img = document.createElement('img'); img.className = 'my_img'; img.src = data.src; tarBox.appendChild(img); return 'aaa'; } else { alert(data.msg); } } else { console.log(xhr.statusText); } } }; xhr.onerror = function (e) { console.log(xhr.statusText); } xhr.send(formData); } </script>
服务端upload-ser.php
<?php //print_r($_POST); //print_r($_FILES); $file = $_FILES['my-image-file']; if ($file['error'] == 0) { define('ROOT', __DIR__); if (is_uploaded_file($file['tmp_name'])) { $ext = explode('/', $file['type'])[1]; $filename = "{$file['name']}_" . date("ymdHis") . ".{$ext}"; $mu = move_uploaded_file($file["tmp_name"], ROOT . "/upload/" . $filename); if ($mu) { exit(json_encode(['id' => 1, 'src' => 'upload/' . $filename])); } else { exit(json_encode(['id' => 2, 'msg' => 'move file fail'])); } } else { exit(json_encode(['id' => 2, 'msg' => 'failed no post'])); } } else { exit(json_encode(['id' => 2, 'msg' => $file['error']])); }
在页面中,我们直接Ctrl+V后, 可以先通过打印POST和FILES看下数据
username 是自定义的post数据,my-image-file是file数据.
console.log打印:
通过xhr返回callback得到上传后的信息
查看上传的目录
GIF