拖拽上传图片
拖拽上傳圖片
?http://www.cnblogs.com/nh11/archive/2011/12/01/2267578.html
很久沒有寫過博客了,閑的時候沒東西可寫,忙的時候沒有時間寫。
前些天,后臺的同事提建議說,上傳圖片不是很好用,后臺在線編輯器用的是fckeditor。
這時候想到了很久前看過一遍提升用戶體驗:HTML5 拖放文件上傳,于是就打算做一個拖拽上傳圖片的功能。
因為是后臺用,所以不用考慮ie的兼容了。
1.拖圖片進瀏覽器的時候阻止瀏覽器的默認行為(比如打開直接圖片)
dropbox 給我們的容器添加上幾個事件綁定dragenter,dragover,drop三個事件
dropbox.addEventListener("dragenter", function(e){ e.stopPropagation(); e.preventDefault(); }, false); dropbox.addEventListener("dragover" , function(e){ e.stopPropagation(); e.preventDefault(); }, false); dropbox.addEventListener("drop", function(e){ e.stopPropagation(); //個人的理解是,若在dropbox上的drop事件被監聽多次,則兩外的事件綁定無效了(不知道對不對) e.preventDefault(); //阻止默認動作 e.dataTransfer.files//一個file類型的數組,就是你拖拽進來的文件 }, false);
2.在得到一個文件file后,要把它顯示出來
預覽圖片要用到FileReader
1 var rd=new FileReader(); 2 rd.onloadend=function(e){ 3 var img=document.createElement('img');//創建一個圖片 4 img.src=this.result;//result就是讀出來的內容 5 img.width=100; 6 img.title=file.name;//文件的原始名稱 7 8 } 9 rd.readAsDataURL({file}); // 讀取為dataurlFilereader有下面幾種方法,預覽圖片用到的是readAsDataURL。
| abort | none | 中斷讀取 |
| readAsBinaryString | file | 將文件讀取為二進制碼 |
| readAsDataURL | file | 將文件讀取為 DataURL |
| readAsText | file, [encoding] | 將文件讀取為文本 |
?
?
?
?
3.把圖片發送到服務端,進行處理
?要提交到服務器,我們必須把圖片讀取為二進制的格式,這里就用到了Filereader的readAsBinaryString
1 var reader = new FileReader(); 2 reader.readAsBinaryString({file}); 3 4 reader.onloadend = function(){ 5 //bug(this.readyState); // 這個時候 應該是 2 6 //bug(this.result); //讀取完成回調函數,數據保存在result中 7 var fileData=this.result; 8 var CRLF="\r\n"; 9 var xhr = new XMLHttpRequest(); 10 xhr.open('post', self.server, true); 11 //xhr.onreadystatechange=function(){}; 12 var boundary='------OTkwNzI0OTEx----';//一段隨機字符串,最好根據時間來生成,為了分割多個表單項 13 // 模擬一個文件提交請求 14 xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary); 15 //xhr.setRequestHeader("Content-Length", file.size); 在chrome下會出錯,可能是出于安全考慮,不允許這樣做 16 var body = ''; 17 body += '--' + boundary + CRLF; 18 body += 'Content-Disposition: form-data; name="'+{fileFieldName}+'"; filename="' + file.name + '"'+CRLF; 19 body += "Content-Type: "+file.type+CRLF+CRLF; 20 body += fileData + CRLF; 21 body += "--" + boundary + "--"+CRLF; 22 xhr.onreadystatechange = function (aEvt) { 23 if (xhr.readyState == 4) { 24 if (xhr.status == 200) 25 alert(xhr.responseText); 26 else 27 console.log('Error', xhr.statusText); 28 } 29 }; 30 31 xhr.sendAsBinary(body); 32 33 34 35 } 上面代碼的第18行filename直接用的原文件名稱,并沒有改名,這在原名為漢字的情況下會提示錯誤,應該處理一下,但不知道怎么弄
?
| application/x-www-form-urlencoded | 在發送前編碼所有字符(默認) |
| multipart/form-data | 不對字符編碼。 在使用包含文件上傳控件的表單時,必須使用該值。 |
| text/plain | 空格轉換為 "+" 加號,但不對特殊字符編碼。 |
上面是在w3cschool搜到的,既然multipart/form-data不對字符編碼,但為什么會出錯,希望知道的能告訴一聲
模擬出來的數據要以二進制發送。火狐XMLHttpRequest 對象中有sendAsBinary()方法,這個是火狐私有的。chrome中沒有,但是可以模擬sendAsBinary
服務端接收文件時和普通上傳文件時一樣
例如php代碼:
?
?4.顯示上傳進度
1 var xhr = new XMLHttpRequest(); 2 upload =xhr.upload; 3 upload.addEventListener("progress", updateProgress, false);//updateProgress 處理上傳進度 4 xhr.open('post', “服務端url”, true); 5 6 function updateProgress(evt) { 7 if (evt.lengthComputable) { 8 var percentComplete = Math.round((evt.loaded * 100) / evt.total) 9 bug(percentComplete); 10 11 } 12 else { 13 // Unable to compute progress information since the total size is unknown 14 } 15 }?
這個也挺簡單,代碼如上,不過要注意的是:
1.事件要綁定到?XMLHttpRequest的 upload上,這樣才能監聽上傳進度。?XMLHttpRequest上同時也有progress事件,不過是監聽下載的。
2. 火狐和chrome調用updateProgress頻率好像一樣,具體是每秒調用一次還是怎么著,我也不是很清楚。假如文件很小,而且網絡很快(本地測試的,當然快)FF就不會觸發progress事件。
? ?在火狐下, 在上傳完成時也不觸發事件所以總是導致進度到不了100%,到了百分之80,90就不動了。
?
好了,功能基本都實現了,另外上面那些代碼都是我在寫篇文章是復制過來的(寫了將近一個星期的時間,有空就寫,程序基本功能完成是在兩個星期前。)。
最后在附上一個我搜索資料過程中找到的一個jquery 插件?jquery-filedrop。
源碼下載
總結
- 上一篇: 网页爬虫汇总
- 下一篇: js实现焦点进入文本框内关闭输入法:im