目前有一個需求,需要在頁面中獲取QQ、微信等軟件的截圖上傳到服務器,爲了用戶體驗,不能讓用戶主動上傳,提供給用戶方法,在web頁面使用粘貼快捷鍵,就可以粘貼到頁面,然後點擊發送進行上傳。而且用戶如果粘貼的是文字也需要能正常發送文字內容。
這個需求需要分爲四個部分:
1、構造頁面,存放獲取的數據
2、獲取粘貼板中的內容
3、在頁面展示獲取的內容
4、將獲取的圖片內容發送到服務器存儲
首先看第一部分,構造頁面,這裏省去其他部分,主要介紹這個功能,因此只需要在body標籤中存在兩個div,一個存儲展示的圖片,一個用於輸入文字。在默認情況下可以輸入文字,因此這時展示圖片的div是隱藏狀態,具體代碼如下:
<body> <div id="jietuWrap" class="b1" style="display:none;"> <img id="jietuImg" src=""> <br /> <button class="sendBtn" onclick="send_msg()">發送</button> </div> <div class="b1"> <textarea id="dope" class="newtextarea" style="width: 99%; border: none; outline: none; resize: none; font-size: 15px; color: black;" onkeydown="suball()"></textarea> <br /> <button class="sendBtn" onclick="send_msg()">發送</button> </div> </body>
然後是第二、三部分,獲取粘貼板的內容並展示,可以通過window對象的子對象clipboardData對象獲取,其中保存了複製、剪切、粘貼的內容,這裏只需要用到粘貼部分。ClipboardEvent對象中就包含了clipboardData對象,我們在監聽到粘貼事件時,就可以獲取到ClipboardEvent,然後獲取到clipboardData對象,它是一個DataTransfer類型的對象,DataTransfer是拖動產生的一個對象,但實際上粘貼事件也是它:
從其中可以看到,data就是獲取到的clipboardData對象對象,具體內容如下:
dropEffect: "none" effectAllowed: "uninitialized" files: FileList {length: 0} items: DataTransferItemList 0: DataTransferItem kind: "file" type: "image/png" __proto__: DataTransferItem getAsFile: ƒ getAsFile() getAsString: ƒ getAsString() kind: (...) type: (...) webkitGetAsEntry: ƒ webkitGetAsEntry() constructor: ƒ DataTransferItem() Symbol(Symbol.toStringTag): "DataTransferItem" get kind: ƒ () get type: ƒ () __proto__: Object length: 1 __proto__: DataTransferItemList types: ["Files"] __proto__: DataTransfer
這是獲取粘貼板的內容,所以最主要用到的是items對象,items是一個DataTransferItemList對象,裏面是DataTransferItem類型的數據。items的DataTransferItem有兩個屬性kind和type:
kind |
String或者file |
type |
具體的數據類型,比如字符串類型或者是文件的類型,即MIME-TYPE |
比如這裏的例子中kind就是file,type是image/png。
還要用到一個方法來獲取具體的文件或字符串的內容,即示例中的getAsFile()和getAsString()方法,從名字就可以看出來獲取圖片等文件就用getAsFile(),獲取字符串就用getAsString()。
上面的例子就可以通過var blob=data.items[0].getAsFile();來獲取圖片內容。然後獲取圖片的base64流,通過ajax就可以上傳到服務器。
下面列出第一部分,獲取剪切板中的內容的代碼:
//綁定粘貼事件 Ctrl+V bindPaste(); //綁定粘貼事件 function bindPaste(){ //定義變量存儲獲取的圖片內容 var blob; //獲取body對象 var body = document.getElementsByTagName("body"); //定義body標籤綁定的粘貼事件處理函數 var fun=function(e){ //獲取clipboardData對象 var data=e.clipboardData||window.clipboardData; //獲取圖片內容 blob=data.items[0].getAsFile(); //判斷是不是圖片,最好通過文件類型判斷 var isImg=(blob&&1)||-1; var reader=new FileReader(); if(isImg>=0){ //將文件讀取爲 DataURL reader.readAsDataURL(blob); } //文件讀取完成時觸發 reader.onload=function(event){ //獲取base64流 var base64_str=event.target.result; //div中的img標籤src屬性賦值,可以直接展示圖片 $("#jietuImg").attr("src",base64_str); //顯示div $("#jietuWrap").css("display","block"); //隱藏輸入文字的div $("#jietuWrap").next().css("display","none"); } } //通過body標籤綁定粘貼事件,注意有些標籤綁定粘貼事件可能出錯 body[0].removeEventListener('paste',fun); body[0].addEventListener('paste',fun); }
最後就是將獲取的圖片的base64流通過ajax發送到服務器存儲到資源服務器了,前端ajax大致如下:
// 上傳的數據除了圖片外,還可以包含自己需要傳遞的參數 var data = { userId : $('#userId').val(), base64 : savedPictureContent }; $.ajax({ type : "POST", url : "${ctx}/../jsp/fileInfo/sendPrintScreen.action", dataType : "json", data : data, success : function(data) { var res = data.result; if (!res) { alert("上傳失敗!"); } else { alert("上傳成功!"); } }, error : function() { alert("由於網絡原因,上傳失敗。"); } });
後端處理代碼:
/** * base64圖片上傳(截圖) */ @RequestMapping("/sendPrintScreen") public void sendPrintScreen(String userId,String base64){ MultipartFile sendFile=BASE64DecodedMultipartFile.base64ToMultipartFile(base64); //上傳文件的工具類 this.sendFileUtil(sendFile userId); }