斷點續傳
最近在優化之前的下載流程,僅此篇幅留作筆記之用,日後其他研究此類問題的夥伴可以馬上了解原理和開發,減少開發成本。
原理:斷點續傳目前比較通用的是使用HTTP續傳方式,相關的資料可以通過訪問:這邊簡單的說明下--HTTP是(超文本傳輸協議),而HTTP又是基於TCP/IP協議之上的協議,好了這邊我們不需要了解的太深,知道它是超文本傳輸協議就好了,即維繫(服務器Server)和(客戶端Client)之間的傳輸協議;
思路:通過超鏈接(可以是你的FTP服務器或者任意的可訪問地址)下載然後本地文件根目錄(最終目標保存)進行保存。中間的方式採用超文本傳輸協議(HTTP)完成;
1-首先定義一個臨時文件格式PERSIST_EXP,用於保存已經下載的臨時文件;
/// <summary> /// temporary file byte /// </summary> public static string PERSIST_EXP = ".cdel";
2-更新下載的核心方法;
public void download(string url, string path) { if (File.Exists(path)) { if (MessageBox.Show("文件己存在!是否重新下載?", "Confirm Message", MessageBoxButton.OKCancel, MessageBoxImage.Question) == MessageBoxResult.OK) { File.Delete(path);//先刪除後重新下載 ResumeDownload(url, path); } else return; } else { //續傳 ResumeDownload(url, path); } } private void ResumeDownload(string url, string path) { path = path + PERSIST_EXP; simpleDownload(url, path);//開始下載 }
3-續傳核心方法:使用HttpWebRequest類從客戶端發送URL(這個URL就是服務器地址)給服務器請求響應,然後服務器返回一個Request信息。具體的HttpWebRequest介紹可以訪問:https://msdn.microsoft.com/zh-cn/library/system.net.httpwebrequest.aspx。 然後通過WebResponse進行資源的響應獲取真正的源信息。接下來就是隨心所欲的操作了。
HttpWebRequest request = getWebRequest(url, 0); WebResponse response = null; response = request.GetResponse(); totalLength = response.ContentLength; Stream reader = response.GetResponseStream(); await Task.Run(() => UpdateProcess(reader, currentLength, writer, totalLength, path, response));//開闢一條新的進程,用於執行任務,主線程直接結束;
4-通過字節逐個讀取並寫入臨時文件;(其中需要注意的是字節reader對象、writer對象、還有響應的response讀取完成之後需要清除和釋放)
private void UpdateProcess(Stream reader, long currentLength, FileStream writer, long totalLength, string path, WebResponse response) { byte[] buff = new byte[1024]; int c = 0; //實際讀取的字節數 while ((c = reader.Read(buff, 0, buff.Length)) > 0) { currentLength += c; writer.Write(buff, 0, c); this.Dispatcher.Invoke(() => progressBar(currentLength, totalLength));//進度條 writer.Flush(); } close(writer); if (currentLength == totalLength) { File.Move(path, path.Replace(PERSIST_EXP, "")); MessageBox.Show("下載完成!"); } if (reader != null) { reader.Close(); reader.Dispose(); response.Close(); } }
5- 還未下載完成然後斷開,第二次啓動的時候就需要檢索當前的字節讀取範圍以及剩下的字節還有多少需要讀取,保證讀取的完整性;
request = getWebRequest(url, (int)lStartPos);//設置Range值 writer.Seek(lStartPos, SeekOrigin.Begin);//指針跳轉 response = request.GetResponse(); totalLength = response.ContentLength + lStartPos; //總長度 currentLength = lStartPos; //當前長度