• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

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

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

/* .Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (C# DIY HttpWebClient)
* Reflector 了一下 System.Net.WebClient ,改写或增加了若干:
* DownLoadUpload 相关方法!
* DownLoad 相关改动较大!
增加了 DataReceiveExceptionOccurrs 事件!
了解服务器端与客户端交互的 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 ,改写或增加了若干:
* DownLoadUpload 相关方法!
增加了 DataReceiveExceptionOccurrs 事件
*/
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 FileNamestring AttachmentName,int Positionint Lengthbyte[] 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 FileNamestring AttachmentName,int Positionint 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 FileNamestring AttachmentName,int Positionint 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 Sstring s, int Iint 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 Addressstring FileNameint ChunksCount)
{
int 0; // position
int 0; // chunk size
string = null;
HttpWebRequest hwrq;
HttpWebResponse hwrp = null;
try
{
hwrq = (HttpWebRequestWebRequest.Create(this.GetUri(Address));
hwrp = (HttpWebResponsehwrq.GetResponse();
long L = hwrp.ContentLength;
hwrq.Credentials this.m_credentials;
L = ((L == -1) || (L > 0x7fffffff)) ? ((long0x7fffffff) : L//Int32.MaxValue 该常数的值为 2,147,483,647; 即十六进制的 0x7FFFFFFF
int = (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 = (hwrp.Headers["Accept-Ranges"] != null & hwrp.Headers["Accept-Ranges"] == "bytes");
hwrp.Headers["Content-Disposition"]//attachment
if (!= null)
{
a.Substring(a.LastIndexOf("filename=") + 9);
}
else
{
FileName;
}
int ss s;
if (b)
{
ChunksCount;
if (64 1024//块大小至少为 128 K 字节
{
64 1024;
}
ss s;
int 0;
while (s)
{
-= s;
if (s)
{
+= l;
}
if (i++ > 0)
{
DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePathFileName, a, p, s, newThreadCallbackHandler(this.DownloadFileChunk));
// 单线程下载
// x.StartDownloadFileChunk();
x.httpWebClient this;
//多线程下载
Thread = new Thread(new ThreadStart(x.StartDownloadFileChunk));
//this.OnThreadProcess(t);
t.Start();
}
+= 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.AbsolutePathFileName, a, p, s);
ExceptionEventArgs eea = new ExceptionEventArgs(e, x);
ExceptionOccurrs(this, eea);
ea eea.ExceptionAction;
}
if (ea == ExceptionActions.Throw)
{
if (!(is WebException) && !(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 Addressstring FileNameint FromPosition, int Length)
{
HttpWebResponse hwrp = null;
string = null;
try
{
//this._FileName = FileName;
HttpWebRequest hwrq = (HttpWebRequestWebRequest.Create(this.GetUri(Address));
//hwrq.Credentials = this.m_credentials;
hwrq.AddRange(FromPosition);
hwrp = (HttpWebResponsehwrq.GetResponse();
hwrp.Headers["Content-Disposition"]//attachment
if (!= null)
{
a.Substring(a.LastIndexOf("filename=") + 9);
}
else
{
FileName;
}
byte[] buffer this.ResponseAsBytes(Address, hwrp, LengthFileName);
// lock (_SyncLockObject)
// {
// this._Bytes += buffer.Length;
// }
}
catch (Exception e)
{
ExceptionActions ea ExceptionActions.Throw;
if (this.ExceptionOccurrs != null)
{
DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePathFileName, a, FromPosition, Length);
ExceptionEventArgs eea = new ExceptionEventArgs(e, x);
ExceptionOccurrs(this, eea);
ea eea.ExceptionAction;
}
if (ea == ExceptionActions.Throw)
{
if (!(is WebException) && !(is SecurityException))
{
throw new WebException("net_webclient", e);
}
throw;
}
}
}
internal byte[] ResponseAsBytes(string RequestURL, WebResponse Responselong LengthstringFileName)
{
string = null//AttachmentName
int P = 0; //整个文件的位置指针
int num2 0;
try
{
Response.Headers["Content-Disposition"]//attachment
if (!= null)
{
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[(intnum1];
int 0; //本块的位置指针
string Response.Headers["Content-Range"];
if (!= null)
{
s.Replace("bytes """);
s.Substring(0, s.IndexOf("-"));
P = Convert.ToInt32(s);
}
int num3 0;
Stream S = Response.GetResponseStream();
do
{
num2 = S.Read(buffer1, num3, ((intnum1) - num3);
num3 += num2;
if (flag1 && (num3 == num1))
{
num1 += 0x10000;
byte[] buffer2 = new byte[(intnum1];
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


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
c#中Split等分割字符串的几种方法(转)发布时间:2022-07-10
下一篇:
SQL Server类型与C#类型对应关系发布时间:2022-07-10
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap