首页 > 学院 > 开发设计 > 正文

C#: 实现支持断点续传多线程下载

2019-11-17 03:13:34
字体:
来源:转载
供稿:网友
C#: 实现支持断点续传多线程下载

/* .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)

上一篇:Random的实现原理

下一篇:c#写扩展方法

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表