C# 断点续传原理与实现
在了解HTTP斷點續傳的原理之前,讓我們先來了解一下HTTP協議,HTTP協議是一種基于tcp的簡單協議,分為請求和回復兩種。請求協議是由 客戶機(瀏覽器)向服務器(WEB SERVER)提交請求時發送報文的協議。回復協議是由服務器(web server),向客戶機(瀏覽器)回復報文時的協議。請求和回復協議都由頭和體組成。頭和體之間以一行空行為分隔。
以下是一個請求報文與相應的回復報文的例子:?
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
….
下面我們就來說說"斷點續傳",顧名思義,斷點續傳就是在上一次下載時斷開的位置開始繼續下載。?
在HTTP協議中,可以在請求報文頭中加入Range段,來表示客戶機希望從何處繼續下載。?
比如說從第1024字節開始下載,請求報文如下:
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
.NET中的相關類
明白了上面的原理,那么,我們來看看.NET FRAMEWORK中為我們提供了哪些類可以來做這些事。
完成HTTP請求
System.Net.HttpWebRequest
HttpWebRequest 類對 WebRequest 中定義的屬性和方法提供支持,也對使用戶能夠直接與使用 HTTP 的服務器交互的附加屬性和方法提供支持。
HttpWebRequest 將發送到 Internet 資源的公共 HTTP 標頭值公開為屬性,由方法或系統設置。下表包含完整列表。可以將 Headers 屬性中的其他標頭設置為名稱/值對。但是注意,某些公共標頭被視為受限制的,它們或者直接由 API公開,或者受到系統保護,不能被更改。Range也屬于被保護之列,不過,.NET為開發者提供了更方便的操作,就是 AddRange方法,向請求添加從請求數據的開始處或結束處的特定范圍的字節范圍標頭
完成文件訪問
System.IO.FileStream
FileStream 對象支持使用Seek方法對文件進行隨機訪問, Seek 允許將讀取/寫入位置移動到文件中的任意位置。這是通過字節偏移參考點參數完成的。字節偏移量是相對于查找參考點而言的,該參考點可以是基礎文件的開始、 當前位置或結尾,分別由SeekOrigin類的三個屬性表示。
代碼實現
了解了.NET提供的相關的類,那么,我們就可以方便的實現了。
代碼如下:
static void Main(string[] args)?
{
string StrFileName="c:\\aa.zip"; //根據實際情況設置?
string StrUrl="http://www.xxxx.cn/xxxxx.zip?"; //根據實際情況設置
//打開上次下載的文件或新建文件?
long lStartPos =0;?
System.IO.FileStream fs;?
if (System.IO.File.Exists(StrFileName))?
{?
fs= System.IO.File.OpenWrite(StrFileName);?
lStartPos=fs.Length;?
fs.Seek(lStartPos,System.IO.SeekOrigin.Current); //移動文件流中的當前指針?
}?
else?
{?
fs = new System.IO.FileStream(StrFileName,System.IO.FileMode.Create);?
lStartPos =0;?
}
//打開網絡連接?
try?
{?
System.Net.HttpWebRequest request =(System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(StrUrl);?
if ( lStartPos>0)?
request.AddRange((int)lStartPos); //設置Range值
//向服務器請求,獲得服務器回應數據流?
System.IO.Stream ns= request.GetResponse().GetResponseStream();
byte[] nbytes = new byte[512];?
int nReadSize=0;?
nReadSize=ns.Read(nbytes,0,512);?
while( nReadSize >0)?
{?
fs.Write(nbytes,0,nReadSize);?
nReadSize=ns.Read(nbytes,0,512);?
}?
fs.Close();?
ns.Close();?
Console.WriteLine("下載完成");?
}?
catch(Exception ex)?
{?
fs.Close();?
Console.WriteLine("下載過程中出現錯誤:"+ex.ToString());?
}?
}
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/fhbcn/archive/2009/01/15/3789035.aspx
另一個斷點續傳的代碼:
/* .Net/C#: 實現支持斷點續傳多線程下載的工具類?
?* Reflector 了一下 System.Net.WebClient ,改寫或增加了若干:?
?* DownLoad、Upload 相關方法!?
?* 增加了 DataReceive、ExceptionOccurrs 事件?
?*/
namespace Microshaoft.Utils?
{?
?using System;?
?using System.IO;?
?using System.Net;?
?using System.Text;?
?using System.Security;?
?using System.Threading;?
?using System.Collections.Specialized;
?/// <summary>?
?/// 記錄下載的字節位置?
?/// </summary>?
?public class DownLoadState?
?{?
? private string _FileName;
? private string _AttachmentName;?
? private int _Position;?
? private string _RequestURL;?
? private string _ResponseURL;?
? private int _Length;
? private byte[] _Data;
? public string FileName?
? {?
?? get?
?? {?
??? return _FileName;?
?? }?
? }
? public int Position?
? {?
?? get?
?? {?
??? return _Position;?
?? }?
? }
? public int Length?
? {?
?? get?
?? {?
??? return _Length;?
?? }?
? }
? public string AttachmentName?
? {?
?? get?
?? {?
??? return _AttachmentName;?
?? }?
? }
? public string RequestURL?
? {?
?? get?
?? {?
??? return _RequestURL;?
?? }?
? }
? public string ResponseURL?
? {?
?? get?
?? {?
??? return _ResponseURL;?
?? }?
? }
? public byte[] Data?
? {?
?? get?
?? {?
??? return _Data;?
?? }?
? }
? internal DownLoadState(string RequestURL, string ResponseURL, string FileName, string AttachmentName, int Position, int Length, byte[] Data)?
? {?
?? this._FileName = FileName;?
?? this._RequestURL = RequestURL;?
?? this._ResponseURL = ResponseURL;?
?? this._AttachmentName = AttachmentName;?
?? this._Position = Position;?
?? this._Data = Data;?
?? this._Length = Length;?
? }
? internal DownLoadState(string RequestURL, string ResponseURL, string FileName, string AttachmentName, int Position, int Length, ThreadCallbackHandler tch)?
? {?
?? this._RequestURL = RequestURL;?
?? this._ResponseURL = ResponseURL;?
?? this._FileName = FileName;?
?? this._AttachmentName = AttachmentName;?
?? this._Position = Position;?
?? this._Length = Length;?
?? this._ThreadCallback = tch;?
? }
? internal DownLoadState(string RequestURL, string ResponseURL, string FileName, string AttachmentName, int Position, int Length)?
? {?
?? this._RequestURL = RequestURL;?
?? this._ResponseURL = ResponseURL;?
?? this._FileName = FileName;?
?? this._AttachmentName = AttachmentName;?
?? this._Position = Position;?
?? this._Length = Length;?
? }
? private ThreadCallbackHandler _ThreadCallback;
? public HttpWebClient httpWebClient?
? {?
?? get?
?? {?
??? return this._hwc;?
?? }?
?? set?
?? {?
??? this._hwc = value;?
?? }?
? }
? internal Thread thread?
? {?
?? get?
?? {?
??? return _thread;?
?? }?
?? set?
?? {?
??? _thread = value;?
?? }?
? }
? private HttpWebClient _hwc;?
? private Thread _thread;
? //?
? internal void StartDownloadFileChunk()?
? {?
?? if (this._ThreadCallback != null)?
?? {?
??? this._ThreadCallback(this._RequestURL, this._FileName, this._Position, this._Length);?
??? this._hwc.OnThreadProcess(this._thread);?
?? }?
? }
?}
?//委托代理線程的所執行的方法簽名一致?
?public delegate void ThreadCallbackHandler(string S, string s, int I, int i);
?//異常處理動作?
?public enum ExceptionActions?
?{?
? Throw,?
? CancelAll,?
? Ignore,?
? Retry?
?}
?/// <summary>?
?/// 包含 Exception 事件數據的類?
?/// </summary>?
?public class ExceptionEventArgs : System.EventArgs?
?{?
? private System.Exception _Exception;?
? private ExceptionActions _ExceptionAction;
? private DownLoadState _DownloadState;
? public DownLoadState DownloadState?
? {?
?? get?
?? {?
??? return _DownloadState;?
?? }?
? }
? public Exception Exception?
? {?
?? get?
?? {?
??? return _Exception;?
?? }?
? }
? public ExceptionActions ExceptionAction?
? {?
?? get?
?? {?
??? return _ExceptionAction;?
?? }?
?? set?
?? {?
??? _ExceptionAction = value;?
?? }?
? }
? internal ExceptionEventArgs(System.Exception e, DownLoadState DownloadState)?
? {?
?? this._Exception = e;?
?? this._DownloadState = DownloadState;?
? }?
?}
?/// <summary>?
?/// 包含 DownLoad 事件數據的類?
?/// </summary>?
?public class DownLoadEventArgs : System.EventArgs?
?{?
? private DownLoadState _DownloadState;
? public DownLoadState DownloadState?
? {?
?? get?
?? {?
??? return _DownloadState;?
?? }?
? }
? public DownLoadEventArgs(DownLoadState DownloadState)?
? {?
?? this._DownloadState = DownloadState;?
? }
?}
?public class ThreadProcessEventArgs : System.EventArgs?
?{?
? private Thread _thread;
? public Thread thread?
? {?
?? get?
?? {?
??? return this._thread;?
?? }?
? }
? public ThreadProcessEventArgs(Thread thread)?
? {?
?? this._thread = thread;?
? }
?}
?/// <summary>?
?/// 支持斷點續傳多線程下載的類?
?/// </summary>?
?public class HttpWebClient?
?{?
? private static object _SyncLockObject = new object();
? public delegate void DataReceiveEventHandler(HttpWebClient Sender, DownLoadEventArgs e);
? public event DataReceiveEventHandler DataReceive; //接收字節數據事件
? public delegate void ExceptionEventHandler(HttpWebClient Sender, ExceptionEventArgs e);
? public event ExceptionEventHandler ExceptionOccurrs; //發生異常事件
? public delegate void ThreadProcessEventHandler(HttpWebClient Sender, ThreadProcessEventArgs e);
? public event ThreadProcessEventHandler ThreadProcessEnd; //發生多線程處理完畢事件
? private int _FileLength; //下載文件的總大小
? public int FileLength?
? {?
?? get?
?? {?
??? return _FileLength;?
?? }?
? }
? /// <summary>?
? /// 分塊下載文件?
? /// </summary>?
? /// <param name="Address">URL 地址</param>?
? /// <param name="FileName">保存到本地的路徑文件名</param>?
? /// <param name="ChunksCount">塊數,線程數</param>?
? public void DownloadFile(string Address, string FileName, int ChunksCount)?
? {?
?? int p = 0; // position?
?? int s = 0; // chunk size?
?? string a = null;?
?? HttpWebRequest hwrq;?
?? HttpWebResponse hwrp = null;?
?? try?
?? {?
??? hwrq = (HttpWebRequest) WebRequest.Create(this.GetUri(Address));?
??? hwrp = (HttpWebResponse) hwrq.GetResponse();?
??? long L = hwrp.ContentLength;
??? hwrq.Credentials = this.m_credentials;
??? L = ((L == -1) || (L > 0x7fffffff)) ? ((long) 0x7fffffff) : L; //Int32.MaxValue 該常數的值為 2,147,483,647; 即十六進制的 0x7FFFFFFF
??? int l = (int) L;
??? this._FileLength = l;
??? //??? 在本地預定空間(竟然在多線程下不用先預定空間)?
??? //??? FileStream sw = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);?
??? //??? sw.Write(new byte[l], 0, l);?
??? //??? sw.Close();?
??? //??? sw = null;
??? bool b = (hwrp.Headers["Accept-Ranges"] != null & hwrp.Headers["Accept-Ranges"] == "bytes");?
??? a = hwrp.Headers["Content-Disposition"]; //attachment?
??? if (a != null)?
??? {?
???? a = a.Substring(a.LastIndexOf("filename=") + 9);?
??? }?
??? else?
??? {?
???? a = FileName;?
??? }
??? int ss = s;?
??? if (b)?
??? {?
???? s = l / ChunksCount;?
???? if (s < 2 * 64 * 1024) //塊大小至少為 128 K 字節?
???? {?
????? s = 2 * 64 * 1024;?
???? }?
???? ss = s;?
???? int i = 0;?
???? while (l > s)?
???? {?
????? l -= s;?
????? if (l < s)?
????? {?
?????? s += l;?
????? }?
????? if (i++ > 0)?
????? {?
?????? DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, p, s, new ThreadCallbackHandler(this.DownloadFileChunk));?
?????? //?????? 單線程下載?
?????? //?????? x.StartDownloadFileChunk();
?????? x.httpWebClient = this;?
?????? //多線程下載?
?????? Thread t = new Thread(new ThreadStart(x.StartDownloadFileChunk));?
?????? //this.OnThreadProcess(t);?
?????? t.Start();
????? }?
????? p += s;?
???? }?
???? s = ss;?
???? byte[] buffer = this.ResponseAsBytes(Address, hwrp, s, FileName);?
???? this.OnThreadProcess(Thread.CurrentThread);
???? //??? lock (_SyncLockObject)?
???? //??? {?
???? //???? this._Bytes += buffer.Length;?
???? //??? }?
??? }?
?? }?
?? catch (Exception e)?
?? {?
??? ExceptionActions ea = ExceptionActions.Throw;?
??? if (this.ExceptionOccurrs != null)?
??? {?
???? DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, p, s);?
???? ExceptionEventArgs eea = new ExceptionEventArgs(e, x);?
???? ExceptionOccurrs(this, eea);?
???? ea = eea.ExceptionAction;?
??? }
??? if (ea == ExceptionActions.Throw)?
??? {?
???? if (!(e is WebException) && !(e is SecurityException))?
???? {?
????? throw new WebException("net_webclient", e);?
???? }?
???? throw;?
??? }?
?? }
? }
? internal void OnThreadProcess(Thread t)?
? {?
?? if (ThreadProcessEnd != null)?
?? {?
??? ThreadProcessEventArgs tpea = new ThreadProcessEventArgs(t);?
??? ThreadProcessEnd(this, tpea);?
?? }?
? }
? /// <summary>?
? /// 下載一個文件塊,利用該方法可自行實現多線程斷點續傳?
? /// </summary>?
? /// <param name="Address">URL 地址</param>?
? /// <param name="FileName">保存到本地的路徑文件名</param>?
? /// <param name="Length">塊大小</param>?
? public void DownloadFileChunk(string Address, string FileName, int FromPosition, int Length)?
? {?
?? HttpWebResponse hwrp = null;?
?? string a = null;?
?? try?
?? {?
??? //this._FileName = FileName;?
??? HttpWebRequest hwrq = (HttpWebRequest) WebRequest.Create(this.GetUri(Address));?
??? //hwrq.Credentials = this.m_credentials;?
??? hwrq.AddRange(FromPosition);?
??? hwrp = (HttpWebResponse) hwrq.GetResponse();?
??? a = hwrp.Headers["Content-Disposition"]; //attachment?
??? if (a != null)?
??? {?
???? a = a.Substring(a.LastIndexOf("filename=") + 9);?
??? }?
??? else?
??? {?
???? a = FileName;?
??? }
??? byte[] buffer = this.ResponseAsBytes(Address, hwrp, Length, FileName);?
??? //?? lock (_SyncLockObject)?
??? //?? {?
??? //??? this._Bytes += buffer.Length;?
??? //?? }?
?? }?
?? catch (Exception e)?
?? {?
??? ExceptionActions ea = ExceptionActions.Throw;?
??? if (this.ExceptionOccurrs != null)?
??? {?
???? DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, FromPosition, Length);?
???? ExceptionEventArgs eea = new ExceptionEventArgs(e, x);?
???? ExceptionOccurrs(this, eea);?
???? ea = eea.ExceptionAction;?
??? }
??? if (ea == ExceptionActions.Throw)?
??? {?
???? if (!(e is WebException) && !(e is SecurityException))?
???? {?
????? throw new WebException("net_webclient", e);?
???? }?
???? throw;?
??? }?
?? }?
? }
? internal byte[] ResponseAsBytes(string RequestURL, WebResponse Response, long Length, string FileName)?
? {?
?? string a = null; //AttachmentName?
?? int P = 0; //整個文件的位置指針?
?? int num2 = 0;?
?? try?
?? {?
??? a = Response.Headers["Content-Disposition"]; //attachment?
??? if (a != null)?
??? {?
???? a = a.Substring(a.LastIndexOf("filename=") + 9);?
??? }
??? long num1 = Length; //Response.ContentLength;?
??? bool flag1 = false;?
??? if (num1 == -1)?
??? {?
???? flag1 = true;?
???? num1 = 0x10000; //64k?
??? }?
??? byte[] buffer1 = new byte[(int) num1];
??? int p = 0; //本塊的位置指針
??? string s = Response.Headers["Content-Range"];?
??? if (s != null)?
??? {?
???? s = s.Replace("bytes ", "");?
???? s = s.Substring(0, s.IndexOf("-"));?
???? P = Convert.ToInt32(s);?
??? }?
??? int num3 = 0;
??? Stream S = Response.GetResponseStream();?
??? do?
??? {?
???? num2 = S.Read(buffer1, num3, ((int) num1) - num3);
???? num3 += num2;?
???? if (flag1 && (num3 == num1))?
???? {?
????? num1 += 0x10000;?
????? byte[] buffer2 = new byte[(int) num1];?
????? Buffer.BlockCopy(buffer1, 0, buffer2, 0, num3);?
????? buffer1 = buffer2;?
???? }
???? //??? lock (_SyncLockObject)?
???? //??? {?
???? //???? this._bytes += num2;?
???? //??? }?
???? if (num2 > 0)?
???? {?
????? if (this.DataReceive != null)?
????? {?
?????? byte[] buffer = new byte[num2];?
?????? Buffer.BlockCopy(buffer1, p, buffer, 0, buffer.Length);?
?????? DownLoadState dls = new DownLoadState(RequestURL, Response.ResponseUri.AbsolutePath, FileName, a, P, num2, buffer);?
?????? DownLoadEventArgs dlea = new DownLoadEventArgs(dls);?
?????? //觸發事件?
?????? this.OnDataReceive(dlea);?
?????? //System.Threading.Thread.Sleep(100);
????? }?
????? p += num2; //本塊的位置指針?
????? P += num2; //整個文件的位置指針?
???? }?
???? else?
???? {?
????? break;?
???? }
??? }?
??? while (num2 != 0);
??? S.Close();?
??? S = null;?
??? if (flag1)?
??? {?
???? byte[] buffer3 = new byte[num3];?
???? Buffer.BlockCopy(buffer1, 0, buffer3, 0, num3);?
???? buffer1 = buffer3;?
??? }?
??? return buffer1;?
?? }?
?? catch (Exception e)?
?? {?
??? ExceptionActions ea = ExceptionActions.Throw;?
??? if (this.ExceptionOccurrs != null)?
??? {?
???? DownLoadState x = new DownLoadState(RequestURL, Response.ResponseUri.AbsolutePath, FileName, a, P, num2);?
???? ExceptionEventArgs eea = new ExceptionEventArgs(e, x);?
???? ExceptionOccurrs(this, eea);?
???? ea = eea.ExceptionAction;?
??? }
??? if (ea == ExceptionActions.Throw)?
??? {?
???? if (!(e is WebException) && !(e is SecurityException))?
???? {?
????? throw new WebException("net_webclient", e);?
???? }?
???? throw;?
??? }?
??? return null;?
?? }?
? }
? private void OnDataReceive(DownLoadEventArgs e)?
? {?
?? //觸發數據到達事件?
?? DataReceive(this, e);?
? }
? public byte[] UploadFile(string address, string fileName)?
? {?
?? return this.UploadFile(address, "POST", fileName, "file");?
? }
? public string UploadFileEx(string address, string method, string fileName, string fieldName)?
? {?
?? return Encoding.ASCII.GetString(UploadFile(address, method, fileName, fieldName));?
? }
? public byte[] UploadFile(string address, string method, string fileName, string fieldName)?
? {?
?? byte[] buffer4;?
?? FileStream stream1 = null;?
?? try?
?? {?
??? fileName = Path.GetFullPath(fileName);?
??? string text1 = "---------------------" + DateTime.Now.Ticks.ToString("x");
??? string text2 = "application/octet-stream";
??? stream1 = new FileStream(fileName, FileMode.Open, FileAccess.Read);?
??? WebRequest request1 = WebRequest.Create(this.GetUri(address));?
??? request1.Credentials = this.m_credentials;?
??? request1.ContentType = "multipart/form-data; boundary=" + text1;
??? request1.Method = method;?
??? string[] textArray1 = new string[7] {"--", text1, "\r\nContent-Disposition: form-data; name=\"" + fieldName + "\"; filename=\"", Path.GetFileName(fileName), "\"\r\nContent-Type: ", text2, "\r\n\r\n"};?
??? string text3 = string.Concat(textArray1);?
??? byte[] buffer1 = Encoding.UTF8.GetBytes(text3);?
??? byte[] buffer2 = Encoding.ASCII.GetBytes("\r\n--" + text1 + "\r\n");?
??? long num1 = 0x7fffffffffffffff;?
??? try?
??? {?
???? num1 = stream1.Length;?
???? request1.ContentLength = (num1 + buffer1.Length) + buffer2.Length;?
??? }?
??? catch?
??? {?
??? }?
??? byte[] buffer3 = new byte[Math.Min(0x2000, (int) num1)];?
??? using (Stream stream2 = request1.GetRequestStream())?
??? {?
???? int num2;?
???? stream2.Write(buffer1, 0, buffer1.Length);?
???? do?
???? {?
????? num2 = stream1.Read(buffer3, 0, buffer3.Length);?
????? if (num2 != 0)?
????? {?
?????? stream2.Write(buffer3, 0, num2);?
????? }?
???? }?
???? while (num2 != 0);?
???? stream2.Write(buffer2, 0, buffer2.Length);?
??? }?
??? stream1.Close();?
??? stream1 = null;?
??? WebResponse response1 = request1.GetResponse();
??? buffer4 = this.ResponseAsBytes(response1);?
?? }?
?? catch (Exception exception1)?
?? {?
??? if (stream1 != null)?
??? {?
???? stream1.Close();?
???? stream1 = null;?
??? }?
??? if (!(exception1 is WebException) && !(exception1 is SecurityException))?
??? {?
???? //throw new WebException(SR.GetString("net_webclient"), exception1);?
???? throw new WebException("net_webclient", exception1);?
??? }?
??? throw;?
?? }?
?? return buffer4;?
? }
? private byte[] ResponseAsBytes(WebResponse response)?
? {?
?? int num2;?
?? long num1 = response.ContentLength;?
?? bool flag1 = false;?
?? if (num1 == -1)?
?? {?
??? flag1 = true;?
??? num1 = 0x10000;?
?? }?
?? byte[] buffer1 = new byte[(int) num1];?
?? Stream stream1 = response.GetResponseStream();?
?? int num3 = 0;?
?? do?
?? {?
??? num2 = stream1.Read(buffer1, num3, ((int) num1) - num3);?
??? num3 += num2;?
??? if (flag1 && (num3 == num1))?
??? {?
???? num1 += 0x10000;?
???? byte[] buffer2 = new byte[(int) num1];?
???? Buffer.BlockCopy(buffer1, 0, buffer2, 0, num3);?
???? buffer1 = buffer2;?
??? }?
?? }?
?? while (num2 != 0);?
?? stream1.Close();?
?? if (flag1)?
?? {?
??? byte[] buffer3 = new byte[num3];?
??? Buffer.BlockCopy(buffer1, 0, buffer3, 0, num3);?
??? buffer1 = buffer3;?
?? }?
?? return buffer1;?
? }
? private NameValueCollection m_requestParameters;?
? private Uri m_baseAddress;?
? private ICredentials m_credentials = CredentialCache.DefaultCredentials;
? public ICredentials Credentials?
? {?
?? get?
?? {?
??? return this.m_credentials;?
?? }?
?? set?
?? {?
??? this.m_credentials = value;?
?? }?
? }
? public NameValueCollection QueryString?
? {?
?? get?
?? {?
??? if (this.m_requestParameters == null)?
??? {?
???? this.m_requestParameters = new NameValueCollection();?
??? }?
??? return this.m_requestParameters;?
?? }?
?? set?
?? {?
??? this.m_requestParameters = value;?
?? }?
? }
? public string BaseAddress?
? {?
?? get?
?? {?
??? if (this.m_baseAddress != null)?
??? {?
???? return this.m_baseAddress.ToString();?
??? }?
??? return string.Empty;?
?? }?
?? set?
?? {?
??? if ((value == null) || (value.Length == 0))?
??? {?
???? this.m_baseAddress = null;?
??? }?
??? else?
??? {?
???? try?
???? {?
????? this.m_baseAddress = new Uri(value);?
???? }?
???? catch (Exception exception1)?
???? {?
????? throw new ArgumentException("value", exception1);?
???? }?
??? }?
?? }?
? }
? private Uri GetUri(string path)?
? {?
?? Uri uri1;?
?? try?
?? {?
??? if (this.m_baseAddress != null)?
??? {?
???? uri1 = new Uri(this.m_baseAddress, path);?
??? }?
??? else?
??? {?
???? uri1 = new Uri(path);?
??? }?
??? if (this.m_requestParameters == null)?
??? {?
???? return uri1;?
??? }?
??? StringBuilder builder1 = new StringBuilder();?
??? string text1 = string.Empty;?
??? for (int num1 = 0; num1 < this.m_requestParameters.Count; num1++)?
??? {?
???? builder1.Append(text1 + this.m_requestParameters.AllKeys[num1] + "=" + this.m_requestParameters[num1]);?
???? text1 = "&";?
??? }?
??? UriBuilder builder2 = new UriBuilder(uri1);?
??? builder2.Query = builder1.ToString();?
??? uri1 = builder2.Uri;?
?? }?
?? catch (UriFormatException)?
?? {?
??? uri1 = new Uri(Path.GetFullPath(path));?
?? }?
?? return uri1;?
? }
?}
}
/// <summary>?
/// 測試類?
/// </summary>?
class AppTest?
{?
?int _k = 0;?
?int _K = 0;
?static void Main()?
?{?
? AppTest a = new AppTest();?
? Microshaoft.Utils.HttpWebClient x = new Microshaoft.Utils.HttpWebClient();
? a._K = 10;
? //訂閱 DataReceive 事件?
? x.DataReceive += new Microshaoft.Utils.HttpWebClient.DataReceiveEventHandler(a.x_DataReceive);?
? //訂閱 ExceptionOccurrs 事件?
? x.ExceptionOccurrs += new Microshaoft.Utils.HttpWebClient.ExceptionEventHandler(a.x_ExceptionOccurrs);
? x.ThreadProcessEnd += new Microshaoft.Utils.HttpWebClient.ThreadProcessEventHandler(a.x_ThreadProcessEnd);?
? string F = "http://localhost/download/phpMyAdmin-2.6.1-pl2.zip?";?
? a._F = F;?
? F = "http://localhost/download/jdk-1_5_0_01-windows-i586-p.aa.exe?";?
? //F = "http://localhost/download/ReSharper1.5.exe?";
? //F = "http://localhost/mywebapplications/WebApplication7/WebForm1.aspx?";?
? //F = "http://localhost:1080/test/download.jsp?";
? //F = "http://localhost/download/Webcast20050125_PPT.zip?";?
? //F = "http://www.morequick.com/greenbrowsergb.zip?";?
? //F = "http://localhost/download/test_local.rar?";?
? string f = F.Substring(F.LastIndexOf("/") + 1);
? //(new System.Threading.Thread(new System.Threading.ThreadStart(new ThreadProcessState(F, @"E:\temp\" + f, 10, x).StartThreadProcess))).Start();
? x.DownloadFile(F, @"E:\temp\temp\" + f, a._K);?
? //? x.DownloadFileChunk(F, @"E:\temp\" + f,15,34556);
? System.Console.ReadLine();?
? //? string uploadfile = "e:\\test_local.rar";?
? //? string str = x.UploadFileEx("http://localhost/phpmyadmin/uploadaction.php?", "POST", uploadfile, "file1");?
? //? System.Console.WriteLine(str);?
? //? System.Console.ReadLine();?
?}
?string bs = ""; //用于記錄上次的位數?
?bool b = false;?
?private int i = 0;?
?private static object _SyncLockObject = new object();?
?string _F;?
?string _f;
?private void x_DataReceive(Microshaoft.Utils.HttpWebClient Sender, Microshaoft.Utils.DownLoadEventArgs e)?
?{?
? if (!this.b)?
? {?
?? lock (_SyncLockObject)?
?? {?
??? if (!this.b)?
??? {?
???? System.Console.Write(System.DateTime.Now.ToString() + " 已接收數據:?????????? ");?
???? //System.Console.Write( System.DateTime.Now.ToString() + " 已接收數據:?????????? ");?
???? this.b = true;?
??? }?
?? }?
? }?
? string f = e.DownloadState.FileName;?
? if (e.DownloadState.AttachmentName != null)?
?? f = System.IO.Path.GetDirectoryName(f) + @"\" + e.DownloadState.AttachmentName;
? this._f = f;
? using (System.IO.FileStream sw = new System.IO.FileStream(f, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, System.IO.FileShare.ReadWrite))?
? {?
?? sw.Position = e.DownloadState.Position;?
?? sw.Write(e.DownloadState.Data, 0, e.DownloadState.Data.Length);?
?? sw.Close();?
? }?
? string s = System.DateTime.Now.ToString();?
? lock (_SyncLockObject)?
? {?
?? this.i += e.DownloadState.Data.Length;?
?? System.Console.Write(bs + "\b\b\b\b\b\b\b\b\b\b" + i + " / " + Sender.FileLength + " 字節數據 " + s);?
?? //System.Console.Write(bs + i + " 字節數據 " + s);?
?? this.bs = new string('\b', Digits(i) + 3 + Digits(Sender.FileLength) + s.Length);?
? }?
?}
?int Digits(int n) //數字所占位數?
?{?
? n = System.Math.Abs(n);?
? n = n / 10;?
? int i = 1;?
? while (n > 0)?
? {?
?? n = n / 10;?
?? i++;?
? }?
? return i;?
?}
?private void x_ExceptionOccurrs(Microshaoft.Utils.HttpWebClient Sender, Microshaoft.Utils.ExceptionEventArgs e)?
?{?
? System.Console.WriteLine(e.Exception.Message);?
? //發生異常重新下載相當于斷點續傳,你可以自己自行選擇處理方式?
? Microshaoft.Utils.HttpWebClient x = new Microshaoft.Utils.HttpWebClient();?
? x.DownloadFileChunk(this._F, this._f, e.DownloadState.Position, e.DownloadState.Length);?
? e.ExceptionAction = Microshaoft.Utils.ExceptionActions.Ignore;?
?}
?private void x_ThreadProcessEnd(Microshaoft.Utils.HttpWebClient Sender, Microshaoft.Utils.ThreadProcessEventArgs e)?
?{?
? //if (e.thread.ThreadState == System.Threading.ThreadState.Stopped)?
? if (this._k ++ == this._K - 1)?
?? System.Console.WriteLine("\nend");?
?}?
}
轉載于:https://www.cnblogs.com/ahjesus/archive/2011/05/26/2057934.html
總結
以上是生活随笔為你收集整理的C# 断点续传原理与实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求助关于系统日志的解决方案
- 下一篇: TCP,UDP发送数据包大小浅析