.Net/C#: 实现支持断点续传多线程下载的 Http Web 客户端工具类 (C# DIY HttpWebClient)

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


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;

  //
  internal void StartDownloadFileChunk()
  {
   if (this._ThreadCallback != null)
   {
    this._ThreadCallback(this._RequestURL, this._FileName, this._Position, this._Length);
   }
  }

 }

 //委托代理线程的所执行的方法签名一致
 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;
  }

 }

 /// <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; //发生异常事件

  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();

       //多线程下载
       //Thread t =
       new Thread(new ThreadStart(x.StartDownloadFileChunk)).Start();
       //t.Start();
      }
      p += s;
     }
     s = ss;
     byte[] buffer = this.ResponseAsBytes(Address, hwrp, s, 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, 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;
    }
   }

  }

  /// <s

阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

playyuer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值