用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