HTTP請求包頭資訊中有一個Range屬性可以指定索取部分HTTP請求的檔案。在.NET中則通過HttpWebRequest.AddRange方法來定義資料的範圍。
當添加了Range屬性的HTTP請求發送後,如果伺服器支援該請求,也就是說支援部分資料提取(也是我們常說到的支援斷點續傳的下載,所謂斷點續傳的下載就是用一個Range屬性來指定沒有下載到的範圍),那麼伺服器會返回Partial Content狀態值。否則會返回OK狀態值(200代碼)。注意如果伺服器支援Range但是HTTP Range請求的範圍超出了檔案範圍,則伺服器會返回RequestedRangeNotSatisfiable狀態值(416代碼)。
代碼:
//+ using System.Net;
//+ using System.IO;
static void Main(string[] args)
{
//建立HTTP請求
var request = (HttpWebRequest)WebRequest.Create("http://files.cnblogs.com/mgen/mgen_amalon.zip");
//從第3個到第12個位元組,共10個位元組。(0是第一個位元組)
request.AddRange(2, 11);
try
{
//擷取HTTP回應,注意HttpWebResponse繼承自IDisposable
using (var response = (HttpWebResponse)request.GetResponse())
{
if(response.StatusCode == HttpStatusCode.OK)
throw new Exception("檔案不支援Range部分下載");
//設定接收資訊的緩衝器
var bytes = new byte[5000];
Console.WriteLine("伺服器回應:{0}", response.StatusCode);
Console.WriteLine("檔案大小:{0}", humanReadableByteCount(response.ContentLength, false));
//擷取回應的Stream(位元組流)
using (var stream = response.GetResponseStream())
using (var outStream = new MemoryStream())
{
long recv = 0;
int count;
//讀取時注意實際接收資料大小
while ((count = stream.Read(bytes, 0, 5000)) != 0)
{
Console.WriteLine("已經下載:{0}", humanReadableByteCount(recv += count, false));
//將接收資料寫入
outStream.Write(bytes, 0, count);
}
//輸出下載的內容
Console.WriteLine(BitConverter.ToString(outStream.ToArray()));
}
}
}
catch (Exception ex)
{
Console.WriteLine("錯誤資訊:{0}", ex.Message);
}
}
//規格化輸出大小的方法
//代碼來自 / Original source
//http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java
public static String humanReadableByteCount(long bytes, bool si)
{
int unit = si ? 1000 : 1024;
if (bytes < unit) return bytes + " B";
int exp = (int)(Math.Log(bytes) / Math.Log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE")[exp - 1] + (si ? "" : "i");
return String.Format("{0:F1} {1}B", bytes / Math.Pow(unit, exp), pre);
}
中間的十個資料會被下載:
如果嘗試不支援Range部分下載的檔案,比如普通HTTP的GET請求指定網址的網頁。程式則會輸出“檔案不支援Range部分下載”。