1. 程式人生 > >web輸入框中實現複製貼上圖片

web輸入框中實現複製貼上圖片

這裡有兩種情況,

  1. 監聽 paste事件可以獲取圖片的Blob資料
  2. 無法獲取,但是這個圖片會以base64的形式插入到網頁中

開始之前先了解一些概念FormData、Blob、File、ArrayBuffer、DataView,可以參考xhr2中的新資料型別
下面分開來講

無法獲取Blob的圖片

比如在firefox中,但是這個圖片會以base64的形式插入到網頁中

我的做法是獲取圖片的base64編碼資料再將其上傳到伺服器
var imgs = $('img', your-editor-selector)

圖片的形式為<img src="data:image/png;base64,iVBO.....>


直接將base64的圖片傳送到伺服器也可以,但我們知道base64的資料要比二進位制大了1/3。所以我們要轉換為二進位制圖片之後再發送到伺服器
獲取圖片base64編碼後的資料 ,假定為 base64_img (值為 IVBO.....)
base64轉二進位制,我這個方法感覺很繁瑣

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
var binary_str = atob(base64_img); //轉為原始編碼
var array = new Uint8Array(new ArrayBuffer(binary_str.length
)); for ( var i = 0; i < binary_str.length; i++) { array[i] = bb.charCodeAt(i); } var dv = new DataView(array.buffer); var blob_img = new Blob([dv], {'type': 'image/png'}); //獲取了blob型別的圖片資料之後就好辦了 var form = new FormData(); form.append('img_name', blob_img); var xhr=new XMLHttpRequest(); xhr.open
('POST', your_img_server); xhr.onload = function (e) { //your code }; xhr.send(form);

這樣服務端就可以獲取到圖片資料了,這和平常用<input type=file>形式上傳沒什麼區別。我用flask測試,服務端獲取圖片的方式是 request.files.get('img_name')

實際的編碼中需要避免重複上傳圖片,怎麼表示兩張圖片是重複的呢,我是通過計算其base64格式的字串的hash值,推薦code.google.com/p/crypto-js的sha1,速度很快

補充一句,怎麼顯示上傳的進度資訊呢?以及傳遞引數
在xhr 的第二版中,新增了一個progress事件,就是表示進度的資訊。

1
2
3
4
5
6
7
8
9
progress_f = function ( event ) {
    if (event.lengthComputable) {
    var percentComplete = event.loaded / event.total * 100;
    var klass = arguments.callee.klass; //這個重點
    var progress_tag = $('.' + klass );
    progress_tag.innerHTML = '正在上傳....'+ percentComplete + '%'
    }
}
progress_f.klass = '123';   //傳遞 k,v 為 klass, 123的引數

監聽 paste事件可以獲取圖片的Blob資料

比如在chrome中,這相對於上一步來說是省略了base64轉Blob的步驟。
為了統一處理,我這裡多此一舉的將Blob轉為base64,然後套用上面的處理邏輯。
監聽paste事件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * 複製貼上圖片,chrome
 * @param  {event} e 
 */
$(your-editor-selector).bind('paste', function(e){
    var clip =  e.originalEvent.clipboardData || e.clipboardData;
    if ( !/image/.test(clip.types[0])) { //只處理圖片
        return true;
    }
    var items = clip.items;
    if ( items ) {
        var img_blob = items[0].getAsFile(); //獲取圖片的blob資料
        var rd = new FileReader();
        rd.onload = function ( e ) {
            var base64_img = rd.result;
            document.execCommand("insertHTML",false,'<img src="' + base64_img + '">');
        }
        rd.readAsDataURL(img_blob);

        e.preventDefault();
    }


});