程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#編程總結(十二)斷點續傳

C#編程總結(十二)斷點續傳

編輯:C#入門知識

我們經常使用下載工具,如bit精靈、迅雷、FlashGet,這些軟件都支持斷點續傳。   斷點續傳即下載任務暫停後可以繼續,而無需重新下載,即下載時需要通知服務器的起始位置。如果允許多線程進行分片下載,必須提供起始-截止位置。說到底就是可以選擇下載某個片段,整個文件的字節流,可以截取流的片段,也能實現流的累積,最終完成文件下載。   一、原理   在 HTTP/1.1裡新增的一個頭屬性:Range,也是現在眾多號稱多線程下載工具(如 FlashGet、迅雷等)實現多線程下載的核心所在。老版本的HTTP協議不支持,所以一些老的服務器還不支持斷點續傳。   Range(請求參數)   用於請求頭中,指定第一個字節的位置和最後一個字節的位置,一般格式:   Range:(unit=first byte pos)-[last byte pos]    例如:Range:100-199,取文件流的100至199之間的字節。   Range:100,取位置為100後的所有字節。如果range 為正值,服務器應該開始發送從指定的 range 參數到 HTTP 實體中數據的末尾之間的數據。   Range:-99,取開始的100個字節。如果range 為負值,服務器應該開始發送從 HTTP 實體中數據的開頭到指定的 range 參數之間的數據。   Content-Range (響應參數)   用於響應頭,指定整個實體中的一部分的插入位置,他也指示了整個實體的長度。在服務器向客戶返回一個部分響應,它必須描述響應覆蓋的范圍和整個實體長度。   一般格式:      Content-Range: bytes (unit first byte pos) - [last byte pos]/[entity legth]  例如:Content-Range: bytes 1024000-1126399/7421120   HTTP協議:http://www.w3.org/Protocols/rfc2616/rfc2616.html   二、C#中實現   在C#中使用AddRange方法向請求添加指定范圍的字節范圍標頭   System.Net.HttpWebRequest 所有的方法:       常用的方法為例:   void AddRange(long from, long to); 指定范圍起始、終止位置,來請求該片段的數據。 復制代碼         // 摘要:         //     向請求添加指定范圍的字節范圍標頭。         //         // 參數:         //   from:         //     開始發送數據的位置。         //         //   to:         //     停止發送數據的位置。         public void AddRange(long from, long to); 復制代碼     我們通過該方法,基於HTTP協議實現了斷點續傳,支持暫停、繼續下載功能,為了更清晰顯示效果,提供了進度條顯示。效果圖:           Request    請求的Range參數,我們可以清晰看到起具體值,這就是請求的片段。在這裡可以清晰的看到HTTP協議版本、請求方法、請求地址等信息       Response   服務器根據請求的Range參數,只返回該片段的數據。我們可以清晰看到Content-Range的具體值。   注意:返回的StatusCode變為了PartialContent,說明是部分數據。   代碼 含義 200 OK     請求成功返回 206 Partial Content     部分數據        下載的核心代碼:       復制代碼         /// <summary>         /// 下載         /// </summary>         public void Download()         {             //從0計數,需要減一             long from = this.currentSize;             if (from < 0)             {                 from = 0;             }               long to = this.currentSize + this.step - 1;             if (to >= this.totalSize && this.totalSize > 0)             {                 to = this.totalSize - 1;             }             this.Download(from, to);         }         /// <summary>         /// 下載         /// </summary>         /// <param name="url"></param>         /// <param name="range"></param>         public void Download(long from,long to)         {             if (this.totalSize == 0)             {                 GetTotalSize();             }             if (from >= this.totalSize || this.currentSize >= this.totalSize)             {                 this.isFinished = true;                 return;             }               HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);             //request.Method = "GET";                         request.AddRange("bytes", from, to);               HttpWebResponse response = (HttpWebResponse)request.GetResponse();             string result = string.Empty;             if (response != null)             {                 byte[] buffer = this.Buffer;                 using (Stream stream = response.GetResponseStream())                 {                     int readTotalSize = 0;                     int size = stream.Read(buffer, 0, buffer.Length);                     while (size > 0)                     {                         //只將讀出的字節寫入文件                         fs.Write(buffer, 0, size);                         readTotalSize += size;                         size = stream.Read(buffer, 0, buffer.Length);                     }                       //更新當前進度                     this.currentSize += readTotalSize;                       //如果返回的response頭中Content-Range值為空,說明服務器不支持Range屬性,不支持斷點續傳,返回的是所有數據                     if (response.Headers["Content-Range"] == null)                     {                         this.isFinished = true;                     }                 }             }         }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved