1. 程式人生 > 實用技巧 >大檔案分步式分片上傳和續傳

大檔案分步式分片上傳和續傳

>>> hot3.png

一,應用場景

1,管理後臺往往需要上傳app包檔案,匯入大量資料檔案等,其檔案大小可能會遠超過php或nginx的上傳限制,為了一個上傳功能,在生產環境修改php或nginx的全域性配置會牽一髮而動全身,不是好的辦法,這時就可以使用分片上傳的方式來解決。

2,網路超時等原因,導致上傳失敗,又需要重傳,通過分片機制,只需要上傳缺失的分片即可。

分片上傳,思路是把大檔案,按照一定大小,分成多塊,分別上傳,上傳完畢後合併出原始檔案。

二,分片上傳的優點

1,可以突破php或nginx上傳大小限制,理論可以上傳無限大資料(當然不能超過伺服器的硬碟大小)。

2,可以使用非同步或多執行緒上傳來提高上傳速度,在javascript中可以使用xmlhttprequest進行非同步上傳,在PHP中可以使用協程庫GuzzleHttp 進行併發上傳,其它語言也可以使用多執行緒的方式上傳,還可以開多個瀏覽器上傳,多個同事一塊傳都可以。

3,斷線重傳,如果在上傳過程中,網路中斷,可以在網路恢復後以塊大小為單位,進行重傳,已經上傳的成功的分片就不需要再次上傳。

三,伺服器架構

1,客戶端負責讀取大檔案,按偏移量分片,併發上傳。

2,分步式檔案系統,用來存上傳的分片,以備合併時拉取。這裡以TFS為例

3,Mysql記錄原始檔案資訊,和各分片資訊。用於分片檢測。

四,上傳流程

服務端介面:

介面1,獲取缺失分片介面,http://.../upload/getMissBlocks?filename=file1&md5=xxx&fileSize=23423

介面2,上傳分片介面,http://.../upload/uploadBlocks?fileId=1&blockId=4&data=...

1,客戶端對分件分片

1.1,客戶端首先獲取本地待上傳檔案大小,最後修改時間,MD5等資訊。

1.2,瞭解伺服器配置情況,最大檔案上傳限制,假設為5M。

1.3,獲取檔案在服務端是否已經存在,通過介面1把檔案的大小,md5值發給服務端檢測是否已經存在。如果不存在繼續檢測該檔案相關分片是否已經存在。如果存在部分分片,則把缺失分片和服務端的分片規則返回給客戶端。

1.4, 客戶端分片,假設要上傳的檔案大小為312M,分片方法為ceil(312/5) = 63片, 每片大小為5M,最後一片大小為2M

1.5, 根據檔案偏移量,對分塊進行編號,比如0-5M blockId=1,5-10M blockId=2

1.6, 傳送非同步請求執行介面2,客戶端將完整檔案大小,MD5, 最後修改時間,分塊數,當前塊ID,當前塊大小和內容一併發給服務端。

(大檔案md5會比較慢,為了提升上傳前的計算效率,建議只對整包進行一次md5, 分片只獲取大小就可以了)

javascript客戶端:可以使用XmlHttpRequest迴圈非同步上傳即可

php或其它語言客戶端: 根據執行緒數或併發數,進行上傳任務分配,然後進行併發上傳。

2,服務端的合併

2.1,服務端收到分片後,先將分片以檔名+編號為作為分片檔名,儲存在分片目錄,為了防止相同的檔名衝突 , 可以將目錄結構設為/path/blocks/{filename}/{fileMD5}/{filename}_{blockid} ,並將所有的分片大小,序號,和整包的MD5,大小等資訊記錄下來(redis/mysql)。

2.2,如果客戶端是同步,而且分片是順序上傳的,可以每上傳一塊,就合併一塊,但如果是非同步併發上傳的,千萬不要每收到一塊就合併一塊,因為服務端很可能會先收到第3塊,後收到第2塊的情況。所以需要先將所有分片先存下來,而只是在服務端進行分片ID計數,等到所有分片上傳完成後,再進行合併操作。

2.3,分片合併,合併的時候,按照分片序號逐一檢測其大小是否與記錄中分片大小相同,如果相同就合併,如果不相同返回錯誤給客戶端,等待後續的重傳。全部合併完成後,對合並出來的整包進行md5進行校驗,如果相同,則上傳成功,否則通知客戶端, 上傳異常。等待重傳。

3,缺失分片檢測

客戶端在上傳前應該先進行分片缺失檢測,可以請求服務端介面來獲取某個檔案所缺失的分片,缺失分片包括,沒有上傳的或上傳不完整的,只需要根據分片上傳的記錄和分片檔案判斷即可。

客戶端收到返回後,只需將缺失的分片上傳即可

4,TFS併發下載

為了更快的下載,可以使用GuzzleHttp庫以協程的方法進行併發下載,因為已經是分塊了,所以一般都不會很大,所以這裡可以不考慮對每個分片再分多塊下載,對於大檔案更精細化的安全下載,可以參考我的另一篇文章。<<大檔案下載斷點續傳>>

5,注意事項及優化

1,注意客戶端上傳前的校驗,本地檔案在伺服器端是否一致,如果不一致要全部重傳。如果存在部分分片應該檢測,服務端分片規則和本地是否一致。

2,注意因為是併發上傳,分片到達伺服器的順序不一定是順序的。大多數情況下最後一片會比平均分片小所以會先傳上去,所以不能以最後一片到達的時機觸發合併行為。而是應該檢查所有分片是否到達.初步檢測分片全部存在後,再合併然後再做最後的md5檢測。

3,優化,TFS並不適用於1M以上的大檔案儲存。可以看公司已有資源情況,使用其它檔案系統。

轉載於:https://my.oschina.net/appnet/blog/1591830