c#.net WebUploader 分塊上傳
IE的自帶下載功能中沒有斷點續傳功能,要實現斷點續傳功能,需要用到HTTP協議中鮮為人知的幾個響應頭和請求頭。
一.兩個必要響應頭Accept-Ranges、ETag
客戶端每次提交下載請求時,服務端都要新增這兩個響應頭,以保證客戶端和服務端將此下載識別為可以斷點續傳的下載:
Accept-Ranges:告知下載客戶端這是一個可以恢復續傳的下載,存放本次下載的開始位元組位置、檔案的位元組大小;
ETag:儲存檔案的唯一標識(我在用的檔名+檔案最後修改時間,以便續傳請求時對檔案進行驗證);
Last-Modified:可選響應頭,存放服務端檔案的最後修改時間,用於驗證
二.一個重要請求頭Range
Range:首次下載時,Range頭為null,此時服務端的響應頭中必須新增響應頭Accept-Ranges、ETag;
續傳請求時,其值表示客戶端已經收到的位元組數,即本次下載的開始位元組位置,服務端依據這個值從相應位置讀取資料傳送到客戶端。
三.用於驗證的請求頭If-Range、
當響應頭中包含有Accept-Ranges、ETag時,續傳請求時,將包含這些請求頭:
If-Range:對應響應頭ETag的值;
Unless-Modified-Since:對應響應頭Last-Modified的值。
續傳請求時,為了保證客戶端與服務端的檔案的一致性和正確性,有必要對檔案進行驗證,驗證需要自己寫驗證程式碼,就根據解析這兩個請求頭的值,將客戶端已下載的部分與服務端的檔案進行對比,如果不吻合,則從頭開始下載,如果吻合,則斷點續傳。
四.速度限制
程式中加入了速度限制,用於對客戶端進行許可權控制的流量限制。
五.其它注意事項
如:檔名亂碼的問題、檔名中空格變加號、強制客戶端顯示下載對話方塊等,詳見原始碼註釋:
1
2/// <summary>
3///下載檔案,支援大檔案、續傳、速度限制。支援續傳的響應頭Accept-Ranges、ETag,請求頭Range 。
4/// Accept-Ranges:響應頭,向客戶端指明,此程序支援可恢復下載.實現後臺智慧傳輸服務(BITS),值為:bytes;
5/// ETag:響應頭,用於對客戶端的初始(200)響應,以及來自客戶端的恢復請求,
6///必須為每個檔案提供一個唯一的ETag值(可由檔名和檔案最後被修改的日期組成),這使客戶端軟體能夠驗證它們已經下載的位元組塊是否仍然是最新的。
7/// Range:續傳的起始位置,即已經下載到客戶端的位元組數,值如:bytes=1474560- 。
8///另外:UrlEncode編碼後會把檔名中的空格轉換中+(+轉換為%2b),但是瀏覽器是不能理解加號為空格的,所以在瀏覽器下載得到的檔案,空格就變成了加號;
9///解決辦法:UrlEncode 之後,將 "+" 替換成 "%20",因為瀏覽器將%20轉換為空格
10/// </summary>
11/// <param name="httpContext">當前請求的HttpContext</param>
12/// <param name="filePath">下載檔案的物理路徑,含路徑、檔名</param>
13/// <param name="speed">下載速度:每秒允許下載的位元組數</param>
14/// <returns>true下載成功,false下載失敗</returns>
15public static bool DownloadFile(HttpContext httpContext,string filePath,long speed)
16{
17bool ret = true;
18try
19{
20--驗證:HttpMethod,請求的檔案是否存在
36
37定義區域性變數
49
50--驗證:檔案是否太大,是否是續傳,且在上次被請求的日期之後是否被修改過--------------
67
68try
69{
70-------新增重要響應頭、解析請求頭、相關驗證-------------------
97
98-------向客戶端傳送資料塊-------------------
108}
109catch
110{
111ret = false;
112}
113finally
114{
115br.Close();
116myFile.Close();
117}
118}
119catch
120{
121ret = false;
122}
123return ret;
124}
上傳展示截圖:
詳細配置資訊可以參考我寫的這篇文章:http://blog.ncmem.com/wordpress/2019/08/09/net%E6%96%AD%E7%82%B9%E7%BB%AD%E4%BC%A0/
歡迎入群一起討論“374992201”