/* .Net/C#:實現支持斷點續傳多線程下載的Http Web客戶端工具類(C# DIY HttpWebClient)* Reflector了一下System.Net.WebClient ,改寫或增加了若干:* DownLoad、Upload相關方法!* DownLoad相關改動較大!*增加了DataReceive、ExceptionOccurrs事件!*了解服務器端與客戶端交互的HTTP協議參閱:*使文件下載的自定義連接支持FlashGet的斷點續傳多線程鏈接下載! jsp/Servlet實現!* http://blog.csdn.net/playyuer/archive/2004/08/02/58430.aspx*使文件下載的自定義連接支持FlashGet的斷點續傳多線程鏈接下載! C#/asp.net實現!* http://blog.csdn.net/playyuer/archive/2004/08/02/58281.aspx*///2005-03-14修訂:/* .Net/C#:實現支持斷點續傳多線程下載的工具類* Reflector了一下System.Net.WebClient ,改寫或增加了若干:* DownLoad、Upload相關方法!*增加了DataReceive、ExceptionOccurrs 事件*/namespaceMicroshaoft.Utils{usingSystem;usingSystem.IO;usingSystem.Net;usingSystem.Text;usingSystem.Security;usingSystem.Threading;usingSystem.Collections.Specialized;/// <summary>///記錄下載的字節位置/// </summary>public classDownLoadState{PRivate string_FileName;private string_AttachmentName;private int_Position;private string_RequestURL;private string_ResponseURL;private int_Length;private byte[]_Data;public stringFileName{get{return_FileName;}}public intPosition{get{return_Position;}}public intLength{get{return_Length;}}public stringAttachmentName{get{return_AttachmentName;}}public stringRequestURL{get{return_RequestURL;}}public stringResponseURL{get{return_ResponseURL;}}public byte[]Data{get{return_Data;}}internalDownLoadState(stringRequestURL,stringResponseURL,stringFileName,stringAttachmentName,intPosition,intLength,byte[]Data){this._FileName=FileName;this._RequestURL=RequestURL;this._ResponseURL=ResponseURL;this._AttachmentName=AttachmentName;this._Position=Position;this._Data=Data;this._Length=Length;}internalDownLoadState(stringRequestURL,stringResponseURL,stringFileName,stringAttachmentName,intPosition,intLength, ThreadCallbackHandler tch){this._RequestURL=RequestURL;this._ResponseURL=ResponseURL;this._FileName=FileName;this._AttachmentName=AttachmentName;this._Position=Position;this._Length=Length;this._ThreadCallback=tch;}internalDownLoadState(stringRequestURL,stringResponseURL,stringFileName,stringAttachmentName,intPosition,intLength){this._RequestURL=RequestURL;this._ResponseURL=ResponseURL;this._FileName=FileName;this._AttachmentName=AttachmentName;this._Position=Position;this._Length=Length;}privateThreadCallbackHandler _ThreadCallback;publicHttpWebClient httpWebClient{get{return this._hwc;}set{this._hwc= value;}}internalThreadthread{get{return_thread;}set{_thread= value;}}privateHttpWebClient _hwc;privateThread_thread;//internal voidStartDownloadFileChunk(){if(this._ThreadCallback!= null){this._ThreadCallback(this._RequestURL,this._FileName,this._Position,this._Length);this._hwc.OnThreadProcess(this._thread);}}}//委托代理線程的所執行的方法簽名一致public delegate voidThreadCallbackHandler(stringS,strings,intI,inti);//異常處理動作public enumExceptionActions{Throw,CancelAll,Ignore,Retry}/// <summary>///包含Exception事件數據的類/// </summary>public classExceptionEventArgs:System.EventArgs{privateSystem.Exception_Exception;privateExceptionActions _ExceptionAction;privateDownLoadState _DownloadState;publicDownLoadState DownloadState{get{return_DownloadState;}}publicException Exception{get{return_Exception;}}publicExceptionActions ExceptionAction{get{return_ExceptionAction;}set{_ExceptionAction= value;}}internalExceptionEventArgs(System.Exceptione, DownLoadState DownloadState){this._Exception =e;this._DownloadState=DownloadState;}}/// <summary>///包含DownLoad事件數據的類/// </summary>public classDownLoadEventArgs:System.EventArgs{privateDownLoadState _DownloadState;publicDownLoadState DownloadState{get{return_DownloadState;}}publicDownLoadEventArgs(DownLoadState DownloadState){this._DownloadState=DownloadState;}}public classThreadProcessEventArgs:System.EventArgs{privateThread_thread;publicThreadthread{get{return this._thread;}}publicThreadProcessEventArgs(Threadthread){this._thread=thread;}}/// <summary>///支持斷點續傳多線程下載的類/// </summary>public classHttpWebClient{private static object_SyncLockObject= newobject();public delegate voidDataReceiveEventHandler(HttpWebClientSender, DownLoadEventArgs e);public eventDataReceiveEventHandler DataReceive;//接收字節數據事件public delegate voidExceptionEventHandler(HttpWebClientSender, ExceptionEventArgs e);public eventExceptionEventHandler ExceptionOccurrs;//發生異常事件public delegate voidThreadProcessEventHandler(HttpWebClientSender, ThreadProcessEventArgs e);public eventThreadProcessEventHandler ThreadProcessEnd;//發生多線程處理完畢事件private int_FileLength;//下載文件的總大小public intFileLength{get{return_FileLength;}}/// <summary>///分塊下載文件/// </summary>/// <param name="Address">URL地址</param>/// <param name="FileName">保存到本地的路徑文件名</param>/// <param name="ChunksCount">塊數,線程數</param>public voidDownloadFile(stringAddress,stringFileName,intChunksCount){intp=0;// positionints=0;// chunk sizestringa= null;HttpWebRequesthwrq;HttpWebResponsehwrp= null;try{hwrq= (HttpWebRequest)WebRequest.Create(this.GetUri(Address));hwrp= (HttpWebResponse)hwrq.GetResponse();longL =hwrp.ContentLength;hwrq.Credentials=this.m_credentials;L = ((L == -1) || (L >0x7fffffff)) ? ((long)0x7fffffff) : L;//Int32.MaxValue該常數的值為2,147,483,647;即十六進制的0x7FFFFFFFintl= (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;boolb= (hwrp.Headers["Accept-Ranges"] != null &hwrp.Headers["Accept-Ranges"] =="bytes");a=hwrp.Headers["Content-Disposition"];//attachmentif(a!= null){a=a.Substring(a.LastIndexOf("filename=") +9);}else{a=FileName;}intss=s;if(b){s=l/ChunksCount;if(s<2*64*1024)//塊大小至少為128 K字節{s=2*64*1024;}ss=s;inti=0;while(l>s){l-=s;if(l<s){s+=l;}if(i++ >0){DownLoadState x= newDownLoadState(Address, hwrp.ResponseUri.AbsolutePath,FileName, a, p, s,newThreadCallbackHandler(this.DownloadFileChunk));//單線程下載// x.StartDownloadFileChunk();x.httpWebClient=this;//多線程下載Threadt= newThread(newThreadStart(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(Exceptione){ExceptionActions ea=ExceptionActions.Throw;if(this.ExceptionOccurrs!= null){DownLoadState x= newDownLoadState(Address, hwrp.ResponseUri.AbsolutePath,FileName, a, p, s);ExceptionEventArgs eea= newExceptionEventArgs(e, x);ExceptionOccurrs(this, eea);ea=eea.ExceptionAction;}if(ea==ExceptionActions.Throw){if(!(eisWebException) && !(eisSecurityException)){thrownewWebException("net_webclient", e);}throw;}}}internal voidOnThreadProcess(Threadt){if(ThreadProcessEnd!= null){ThreadProcessEventArgs tpea= newThreadProcessEventArgs(t);ThreadProcessEnd(this, tpea);}}/// <summary>///下載一個文件塊,利用該方法可自行實現多線程斷點續傳/// </summary>/// <param name="Address">URL地址</param>/// <param name="FileName">保存到本地的路徑文件名</param>/// <param name="Length">塊大小</param>public voidDownloadFileChunk(stringAddress,stringFileName,intFromPosition,intLength){HttpWebResponsehwrp= null;stringa= null;try{//this._FileName = FileName;HttpWebRequesthwrq= (HttpWebRequest)WebRequest.Create(this.GetUri(Address));//hwrq.Credentials = this.m_credentials;hwrq.AddRange(FromPosition);hwrp= (HttpWebResponse)hwrq.GetResponse();a=hwrp.Headers["Content-Disposition"];//attachmentif(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(Exceptione){ExceptionActions ea=ExceptionActions.Throw;if(this.ExceptionOccurrs!= null){DownLoadState x= newDownLoadState(Address, hwrp.ResponseUri.AbsolutePath,FileName, a, FromPosition,Length);ExceptionEventArgs eea= newExceptionEventArgs(e, x);ExceptionOccurrs(this, eea);ea=eea.ExceptionAction;}if(ea==ExceptionActions.Throw){if(!(eisWebException) && !(eisSecurityException)){thrownewWebException("net_webclient", e);}throw;}}}internal byte[]ResponseAsBytes(stringRequestURL,WebResponseResponse,longLength,stringFileName)
新聞熱點
疑難解答