在 了解HTTP斷點續(xù)傳的原理之前,,讓我們先來了解一下HTTP協(xié)議,,HTTP協(xié)議是一種基于tcp的簡單協(xié)議,分為請求和回復(fù)兩種。請求協(xié)議是由客戶機 (瀏覽器)向服務(wù)器(WEB SERVER)提交請求時發(fā)送報文的協(xié)議,?;貜?fù)協(xié)議是由服務(wù)器(web server),向客戶機(瀏覽器)回復(fù)報文時的協(xié)議,。請求和回復(fù)協(xié)議都由頭和體組成,。頭和體之間以一行空行為分隔。 以下是一個請求報文與相應(yīng)的回復(fù)報文的例子: GET /image/index_r4_c1.jpg HTTP/1.1 Accept: */* Referer: http://192.168.3.120:8080 Accept-Language: zh-cn Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705) Host: 192.168.3.120:8080 Connection: Keep-Alive
HTTP/1.1 200 OK Server: Microsoft-IIS/5.0 Date: Tue, 24 Jun 2003 05:39:40 GMT Content-Type: image/jpeg Accept-Ranges: bytes Last-Modified: Thu, 23 May 2002 03:05:40 GMT ETag: "bec48eb862c21:934" Content-Length: 2827 …. 顧名思義,,斷點續(xù)傳就是在上一次下載時斷開的位置開始繼續(xù)下載,。在HTTP協(xié)議中,可以在請求報文頭中加入Range段,,來表示客戶機希望從何處繼續(xù)下載,。 比如說從第1024字節(jié)開始下載,請求報文如下:
GET /image/index_r4_c1.jpg HTTP/1.1 Accept: */* Referer: http://192.168.3.120:8080 Accept-Language: zh-cn Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705) Host: 192.168.3.120:8080 Range:bytes=1024- Connection: Keep-Alive 相應(yīng)的響應(yīng)報文為 HTTP/1.1 206 Partial Content Server: Microsoft-IIS/5.0 Date: Tue, 24 Jun 2003 05:39:40 GMT Content-Type: image/jpeg Accept-Ranges: bytes Last-Modified: Thu, 23 May 2002 03:05:40 GMT ETag: "bec48eb862c21:934" Content-Length: 1803 Content-Range: bytes 1024-1803/2827 通過兩段不同的報文可以看到,,在斷點續(xù)傳時,,我們只要能給客戶端相應(yīng)相應(yīng)的報文,使客戶端能正確響應(yīng),,并且傳送續(xù)傳點后的部分文件即可實現(xiàn)斷點續(xù)傳,。 1. 區(qū)分斷點續(xù)傳報文。 由于斷點續(xù)傳報文中含有Range字段,,因此,,只要通過Request.Headers["Range"]是否為null即可。 2. 發(fā)送正確的續(xù)傳響應(yīng)報文 兩次響應(yīng)報文不同的部分在報文中已經(jīng)用紅色部分標(biāo)識出來,,只需修改紅色部分報文頭,,便能發(fā)送正確的續(xù)傳報文,。 3. 傳送正確的文件部分 續(xù)傳的時候只需要傳送續(xù)傳點之后的文件即可,,首先通過請求報文中的Range字段獲取文件的開始位置,傳送文件的時候只需要傳送該位置之后的部分即可,。 下面的代碼示例顯示了一個可以支持斷點續(xù)傳的 ASP.NET 頁 private void Page_Load(object sender, System.EventArgs e) { string file = MapPath("ff.zip"); FileInfo fi=new FileInfo (file);
long startPos = 0;
//所傳輸?shù)奈募L度 long fileTranLen = fi.Length;
//斷點續(xù)傳請求 if (Request.Headers["Range"] != null) { Response.StatusCode = 206; startPos = long.Parse(Request.Headers["Range"].Replace("bytes=", "").Split('-')[0]); fileTranLen -= startPos;
//Response.AddHeader("Accept-Ranges", "bytes"); //Content-Range: bytes [文件塊的開始字節(jié)]-[傳輸文件的總大小]/[文件的總大小] Response.AddHeader("Content-Range", string.Format("bytes {0}-{1}/{2}",startPos,fileTranLen,fi.Length)); }
Response.AddHeader("Content-Length", fileTranLen.ToString());
//基本的文件下載報文頭 Response.ContentType = "application/octet-stream"; Response.AddHeader("Content-Disposition", "attachment; filename=" + fi.Name);
//簡單的流拷貝 System.IO.Stream fileStream = System.IO.File.OpenRead(file); fileStream.Position = startPos;
byte[] buffer = new Byte[1024]; int count; while ((count = fileStream.Read(buffer, 0, buffer.Length)) > 0) { Response.OutputStream.Write(buffer, 0, count); } fileStream.Close();
Response.End(); } |
|
來自: 昵稱10504424 > 《C#》