目前市場上大多數的網站的斷點上傳都是須要安裝瀏覽器插件的,本文就針對高級瀏覽器的環境下,經過HTML5 File api實現斷點上傳進行說明 html
對於文件上傳,相信還有很多同窗還停留在FLASH時代,其實如今 HTML5 不只能夠實現文件上傳,並且能夠作得更好。 前端
如下是對 HTML5 與 FLASH 就文件上傳方面的功能調研測試得出的結果。 html5
功能描述 | FLASH | HTML5 |
---|---|---|
文件多選 | ✓ | ✓ |
格式過濾 | ✓ | ✓ |
拖拽(文件 & 文件夾) | ✗ | ✓ |
截屏粘貼 | ✗ | ✓ |
Cookie & Session | ✗ | ✓ |
文件內容讀取 | ✓ | ✓ 快150% |
圖片預覽&裁剪 | ✓ | ✓ 快200% |
文件上傳 | ✓ | ✓ 快10% |
進度跟蹤 | ✓ | ✓ 更加精準 |
PS: 截屏粘貼是指,若是剪切板裏面存在圖片數據,是能夠經過 CTRL + V 將此圖片做爲文件添加到文件上傳組件中的。讓剪切板中有圖片數據有不少方式:截屏軟件(如QQ截屏),瀏覽器中右擊圖片點擊複製,QQ聊天軟件中複製圖片... web
上表來源: http://fex.baidu.com/blog/2014/04/html5-uploader/
1、實現文件多選 ajax
HTML5的新增了"multiple"屬性,該屬性可接受多個值的文件上傳字段 算法
<input type="file" multiple="multiple" name="file" id="file">
添加了該屬性用戶就能夠在彈出的對話框中一次性選擇多個文件了 後端
2、實現文件從計算機拖拽到網頁以及添加文件隊列功能 api
這裏咱們用 dragover 和 drop 兩個事件來管理文件拖拽的功能 瀏覽器
其中 dragover 用來處理在指定的元素上移動時的事件,這裏咱們經過給body綁定dragover時間來處理頁面中拖動文件的事件 服務器
document.body.addEventListener('dragover', dragFile, false); function dragFile(evt) { evt.stopPropagation(); evt.preventDefault(); evt.dataTransfer.dropEffect = 'copy'; }
用 drop 事件來處理鼠標鬆開時候的事件,此時應該將用戶拖動過來的文件加入到上傳隊列中,以供後續的處理
document.body.addEventListener('drop', dropFile, false); function dragFile(evt) { evt.stopPropagation(); evt.preventDefault(); // dataTransfer.files屬性能夠獲取到全部拖動選擇的文件,經過遍歷能夠讀取到全部文件的信息。 // 遍歷每一個文件能夠獲取到文件的 name、size、type、lastModifiedDate等關鍵信息 var files = evt.dataTransfer.files; // addfile 方法 用來添加上傳文件隊列,在input的change事件中也須要調用 // 該方法首先檢查有無文件正在上傳中,若是有就將後續加入的文件放到上傳隊列中,若是沒有文件正在上傳就直接執行上傳命令 addfile(files); }
3、文件續傳原理
目前比較經常使用的斷點續傳的方法有兩種,一種是經過websocket接口進行文件上傳,另外一種是經過ajax,兩種方法各有千秋,雖然websocket聽起來比較高端些~ 可是除了用了不一樣的協議外其餘的算法基本上都是很類似的,而且服務端要開啓ws接口,這裏用相對方便的ajax來講明斷點上傳的思路。
說來講去,斷點續傳最核心的內容就是把文件「切片」而後再一片一片的傳給服務器,可是這看似簡單的上傳過程卻有着無數的坑。
首先是文件的識別,一個文件被分紅了若干份以後如何告訴服務器你切了多少塊,以及最終服務器應該如何把你上傳上去的文件進行合併,這都是要考慮的。
所以在文件開始上傳以前,咱們和服務器要有一個「握手」的過程,告訴服務器文件信息,而後和服務器約定切片的大小,當和服務器達成共識以後就能夠開始後續的文件傳輸了。
前臺要把每一塊的文件傳給後臺,成功以後前端和後端都要標識一下,以便後續的斷點。
當文件傳輸中斷以後用戶再次選擇文件就能夠經過標識來判斷文件是否已經上傳了一部分,若是是的話,那麼咱們能夠接着上次的進度繼續傳文件,以達到續傳的功能。
4、文件的前端切片
有了HTML5 的 File api以後切割文件比想一想的要簡單的多的多。
只要用slice 方法就能夠了
var packet = file.slice(start, end);
參數start是開始切片的位置,end是切片結束的位置 單位都是字節。經過控制start和end 就能夠是實現文件的分塊
如
file.slice(0,1000); file.slice(1000,2000); file.slice(2000,3000); // ......
5、文件片斷的上傳
上一部咱們經過slice方法把文件分紅了若干塊,接下來要作的事情就是把這些碎片傳到服務器上。
這裏咱們用ajax的post請求來實現
var xhr = new XMLHttpRequest(); var url = xxx // 文件上傳的地址 能夠包括文件的參數 如文件名稱 分塊數等以便後臺處理 xhr.open('POST', url, true); xhr.onload = function (e){ // 判斷文件是否上傳成功,若是成功繼續上傳下一塊,若是失敗重試該快 } xhr.upload.onprogress = function(e){ // 選用 若是文件分塊大小較大 能夠經過該方法判斷單片文件具體的上傳進度 // e.loaded 該片文件上傳了多少 // e.totalSize 該片文件的總共大小 } xhr.send(packet);
本文地址 http://www.zhuwenlong.com/blog/51f6519532ffd70b27000001