如何實現文件分片上傳[顯示文件上傳進度]

希望有一天大家都能在借鑑中創新

最近沒有在弄這個文件上傳的進度顯示問題,css的特效被落下了。只是因爲之前做了文件上傳,但是並沒有真的思考過這些上傳進度的問題。前幾天看到一個博客,有感而發,覺得這個上傳進度的問題遲早是會被遇到的。在這裏簡單介紹一下一般的實現方法和思路,希望即將踩坑的夥伴,藉助這個文章能脫坑更順利點。

 

 

必備工具:

html css java

爲了偷懶這裏我就直接使用了Springboot框架做爲基礎項目demo來使用.

 

基本框架搭建:

使用Bootstrap集成前端樣式,本來就不擅長樣式編寫,這裏展示的樣式大家就湊合看吧。編寫基本的上傳文件編輯位置即可,這裏重在實現文件分割的業務實現。

實現文件分割的方式可以簡單分爲兩種: ① 定塊分割 ② 定長分割

定塊分割:不管文件的大小是多少,定義文件分割的塊數是制定的。比如我在這個項目中就是用了這種分割方式,定義無論上傳的文件大小是多少都將其分割成10塊。專業角度來看,這種分割方式還是過於粗糙並且存在很多問題的,但是因爲這裏爲了爲展示如何進行文件分割,所以優化分割算法問題可以根據業務問題進行動態變更。

定長分割:相對定塊分割來說,這種方式會稍微好點。根據上傳的文件大小進行分割文件數量,請求上傳接口的次數也根據文件大小變化。

當然,似乎這些方法進行分割似乎都不是最好的,但是文件分割放在客戶端是爲了減少單個大文件上傳導致一個老鼠壞一鍋湯的意外情況。

文件分割:

使用定塊分割文件,簡單的代碼實現:


 

 

/*切割文件方法*/ function sliceFiles(file, num) { var fileList = []; var singleSize = Math.ceil(file.size / num); var location = 0; while (location < file.size) { fileList.push(file.slice(location, location + singleSize)); location += singleSize; } return fileList; }

經獲取到的文件進行上傳,需要後端提供文件上傳藉口,這裏文件上傳使用FormData的方式。接收文件上傳的接口定位爲:

文件分片上傳的目的是爲了實現文件更加迅速的上傳,因此我們如果每次對文件進行分割操作之後,在多次循環調用上傳文件接口和單獨上傳相比沒有任何意義。因此我們這裏吧上傳文件的方式設置成異步方法,等待文件分片結束之後同時執行調用方法。


 

 

function uploadFileSingle(index, file) { return new Promise(function (resolve, reject) { console.log("content--------", index); var formData = new FormData(); formData.append("file", file); formData.append("index", index); $.ajax({ url: '/file/uploadSingle?_t=' + new Date().getMilliseconds(), type: "POST", processData: false, contentType: false, mimeType: "multipart/form-data", data: formData, success: function (data) { resolve.apply(data); }, error: function (data) { reject.apply(data); }, }); }) }

具體調用時:

代碼中提及到的mergeFile方法是爲了將分片上傳的文件進行合併,因爲分片只是目的,合併是爲了將上傳到的文件能夠保持原本的狀態。

合併文件的思路:

說道了文件分塊上傳,就不得不說文件如何合併最終的文件的思路。一個文件還是需要有一個執行的標識,方便最後的收集。分片的文件需要有一定的順序性的標識,比如 0,1,2之類的數字或者其他信息標識這個文件是屬於整個文件分割後的第幾塊文件。我這裏只是爲了演示項目效果,我在分割之後只是單純給他們定義了文件的名字爲:0 1 2 3 4 5 6 7 8 9。

因此我最後在合併文件的時候按照數字順序拿到文件,然後進行合併文件操作即可。

對比效果:

關於這麼分片做的好處實際上有很多,我這邊做了一執行時間的簡單對比。備註:小文件似乎在這裏不佔優勢,因此這裏上傳的文件的大小爲:2.42GB

69.025

62.434

如果有興趣可以嘗試一下,除了我本地的寬帶等性能條件的限制,文件稍微大點的時候會有速度上的提升。

文件合併

文件上傳結束之後需要主動請求數據進行合併,因此可以在Promise的then()方法中發起合併數據文件的請求。

後端java代碼實現:

 

 


 

接下來我們可以在此基礎之上做點有意思的事情,優化上傳等待的交互,追加上傳進度的展示。

需要用到xhr,具體是的使用可以在ajax方法中獲取上傳的的進度數據:


 

 

xhr: function () { var xhr = new XMLHttpRequest(); xhr.upload.addEventListener('progress', function (e) { var progressRate = (e.loaded / e.total) * 100 + '%'; $(`#${index} div`).attr("style", `width: ${progressRate}`); }); return xhr; }

加上進度展示之後會大大優化普通loading等待導致的交互弱勢感覺,看一下最終的效果:

 


 

微信公衆號:碼農的技術分享【更新速度有點慢 多多見諒】

源代碼請私信 文件分片

知乎賬號:曦曦春風

發佈了87 篇原創文章 · 獲贊 17 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章