实现支持断点续传多线程下载的 Http Web 客户端C#工具类

实现支持断点续传多线程下载的 Http Web 客户端C#工具类,第1张

概述实现支持断点续传多线程下载的 Http Web 客户端C#工具

下面是内存溢出 jb51.cc 通过网络收集整理的代码片段。

内存溢出小编现在分享给大家,也给大家做个参考。

/* .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 事件*/ namespace Microshaoft.Utils{using System;using System.IO;using System.Net;using System.Text;using System.Security;using System.Threading;using System.Collections.Specialized; ////// 记录下载的字节位置///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,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,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} ////// 包含 Exception 事件数据的类///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;}} ////// 包含 DownLoad 事件数据的类///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;} } ////// 支持断点续传多线程下载的类///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;}} ////// 分块下载文件////// URL 地址/// 保存到本地的路径文件名/// 块数,线程数public voID Downloadfile(string Address,int ChunksCount){int p = 0; // positionint s = 0; // chunk sizestring 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],l);// sw.Close();// sw = null; bool b = (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;} int ss = s;if (b){s = l / ChunksCount;if (s s){l -= s;if (l 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,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,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);}} ////// 下载一个文件块,利用该方法可自行实现多线程断点续传////// URL 地址/// 保存到本地的路径文件名/// 块大小public voID DownloadfileChunk(string Address,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"]; //attachmentif (a != null){a = a.Substring(a.LastIndexOf("filename=") + 9);}else{a = filename;} byte[] buffer = this.ResponseAsBytes(Address,Length,filename);// lock (_SyncLockObject)// {// this._Bytes += buffer.Length;// }}catch (Exception e){ExceptionActions ea = ExceptionActions.Throw;if (this.ExceptionOccurrs != null){DownLoadState x = new DownLoadState(Address,Fromposition,Length);ExceptionEventArgs eea = new ExceptionEventArgs(e,e);}throw;}}} internal byte[] ResponseAsBytes(string RequestURL,WebResponse Response,long Length,string filename){string a = null; //Attachmentnameint P = 0; //整个文件的位置指针int num2 = 0;try{a = Response.headers["Content-disposition"]; //attachmentif (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,buffer2,num3);buffer1 = buffer2;} // lock (_SyncLockObject)// {// this._bytes += num2;// }if (num2 > 0){if (this.DataReceive != null){byte[] buffer = new byte[num2];Buffer.Blockcopy(buffer1,buffer,buffer.Length);DownLoadState dls = new DownLoadState(RequestURL,Response.ResponseUri.absolutePath,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,buffer3,num3);buffer1 = buffer3;}return buffer1;}catch (Exception e){ExceptionActions ea = ExceptionActions.Throw;if (this.ExceptionOccurrs != null){DownLoadState x = new DownLoadState(RequestURL,num2);ExceptionEventArgs eea = new ExceptionEventArgs(e,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,fIEldname));} public byte[] Uploadfile(string address,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,buffer1.Length);do{num2 = stream1.Read(buffer3,buffer3.Length);if (num2 != 0){stream2.Write(buffer3,num2);}}while (num2 != 0);stream2.Write(buffer2,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,((int) num1) - num3);num3 += num2;if (flag1 && (num3 == num1)){num1 += 0x10000;byte[] buffer2 = new byte[(int) num1];Buffer.Blockcopy(buffer1,num3);buffer1 = buffer2;}}while (num2 != 0);stream1.Close();if (flag1){byte[] buffer3 = new byte[num3];Buffer.Blockcopy(buffer1,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;} } } ////// 测试类///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"; 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,15,34556); System.Console.Readline();// string uploadfile = "e:\test_local.rar";// string str = x.UploadfileEx("http://localhost/phpmyadmin/uploadaction.PHP",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,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");}}

以上是内存溢出(jb51.cc)为你收集整理的全部代码内容,希望文章能够帮你解决所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

总结

以上是内存溢出为你收集整理的实现支持断点续传多线程下载的 Http Web 客户端C#工具类全部内容,希望文章能够帮你解决实现支持断点续传多线程下载的 Http Web 客户端C#工具类所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1237642.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存