zoukankan      html  css  js  c++  java
  • Asp.net 2.0 文件下载[支持多线程, 断点续传功能](示例代码下载)

    (一) . 概述

            最近做了个C/S文件下载工具, 支持多任务, 多线程和断点续传功能. 其中部分代码是从网上找来的, 自己改了

    许多Thread Bug, 并增加多任务, 断点续传等功能.  

            由于公司具有代码所有权, 不能将源代码共享.  自己对比较Asp.net感兴趣, 业余时间自己做了个简单的, 基于

    Asp.net 2.0的, 目前能够执行对一个文件的下载任务, 但已经实现了多线程, 断点续传功能.  根据需要您可以增加

    多任务 功能, 分享一下, 互相学习!  互相借鉴!

           时间仓促, 此程序还没有做很多参数方面的优化. 可以作参考用.

                  

    (二).运行效果

     (三). 代码

      1. 核心 DownLoadState.cs 文件代码

       1 /// <summary>
       2 /// Author: [ ChengKing(ZhengJian) ] 
       3 /// Blog:   Http://blog.csdn.net/ChengKing
       4 /// 注:从网上找了个优秀代码
       5 /// 扩展如下功能: 
       6 ///   1. 解决一些线程相关的Bug; 
       7 ///   2.扩展用控制文件实现断点续传功能.
       8 /// </summary>
       9 namespace DownLoadComponent
      10 {
      11     /// <summary>
      12     /// 多线程辅助类(Add by ChengKing)
      13     /// </summary>
      14     public class Task
      15     {
      16         string _FromFileName;
      17         string _ToFileName;
      18         int _ThreadNum;
      19 
      20         public Task(string FromFileName, string ToFileName, int ThreadNum)
      21         {
      22             this._FromFileName = FromFileName;
      23             this._ToFileName = ToFileName;
      24             this._ThreadNum = ThreadNum;
      25         }
      26 
      27         public string FromFileName
      28         {
      29             get
      30             {
      31                 return _FromFileName;
      32             }
      33             set
      34             {
      35                 _FromFileName = value;
      36             }
      37         }
      38         public string ToFileName
      39         {
      40             get
      41             {
      42                 return _ToFileName;
      43             }
      44             set
      45             {
      46                 _ToFileName = value;
      47             }
      48         }
      49         public int ThreadNum
      50         {
      51             get
      52             {
      53                 return _ThreadNum;
      54             }
      55             set
      56             {
      57                 _ThreadNum = value;
      58             }
      59         }
      60     }
      61 
      62     /// <summary>
      63     /// 记录下载的字节位置
      64     /// </summary>
      65     public class DownLoadState
      66     {
      67         private string _FileName;
      68 
      69         private string _AttachmentName;
      70         private int _Position;
      71         private string _RequestURL;
      72         private string _ResponseURL;
      73         private int _Length;
      74 
      75         private byte[] _Data;
      76 
      77         public string FileName
      78         {
      79             get
      80             {
      81                 return _FileName;
      82             }
      83         }
      84 
      85         public int Position
      86         {
      87             get
      88             {
      89                 return _Position;
      90             }
      91         }
      92 
      93         public int Length
      94         {
      95             get
      96             {
      97                 return _Length;
      98             }
      99         }
     100 
     101 
     102         public string AttachmentName
     103         {
     104             get
     105             {
     106                 return _AttachmentName;
     107             }
     108         }
     109 
     110         public string RequestURL
     111         {
     112             get
     113             {
     114                 return _RequestURL;
     115             }
     116         }
     117 
     118         public string ResponseURL
     119         {
     120             get
     121             {
     122                 return _ResponseURL;
     123             }
     124         }
     125 
     126 
     127         public byte[] Data
     128         {
     129             get
     130             {
     131                 return _Data;
     132             }
     133         }
     134 
     135         internal DownLoadState(string RequestURL, string ResponseURL, string FileName, string AttachmentName, int Position, int Length, byte[] Data)
     136         {
     137             this._FileName = FileName;
     138             this._RequestURL = RequestURL;
     139             this._ResponseURL = ResponseURL;
     140             this._AttachmentName = AttachmentName;
     141             this._Position = Position;
     142             this._Data = Data;
     143             this._Length = Length;
     144         }
     145 
     146         internal DownLoadState(string RequestURL, string ResponseURL, string FileName, string AttachmentName, int Position, int Length, ThreadCallbackHandler tch)
     147         {
     148             this._RequestURL = RequestURL;
     149             this._ResponseURL = ResponseURL;
     150             this._FileName = FileName;
     151             this._AttachmentName = AttachmentName;
     152             this._Position = Position;
     153             this._Length = Length;
     154             this._ThreadCallback = tch;
     155         }
     156 
     157         internal DownLoadState(string RequestURL, string ResponseURL, string FileName, string AttachmentName, int Position, int Length)
     158         {
     159             this._RequestURL = RequestURL;
     160             this._ResponseURL = ResponseURL;
     161             this._FileName = FileName;
     162             this._AttachmentName = AttachmentName;
     163             this._Position = Position;
     164             this._Length = Length;
     165         }
     166 
     167         private ThreadCallbackHandler _ThreadCallback;
     168 
     169         //
     170         internal void StartDownloadFileChunk()
     171         {
     172             if (this._ThreadCallback != null)
     173             {
     174                 this._ThreadCallback(this._RequestURL, this._FileName, this._Position, this._Length);
     175             }
     176         }
     177 
     178     }
     179 
     180     //委托代理线程的所执行的方法签名一致
     181     public delegate void ThreadCallbackHandler(string S, string s, int I, int i);
     182 
     183     //异常处理动作
     184     public enum ExceptionActions
     185     {
     186         Throw,
     187         CancelAll,
     188         Ignore,
     189         Retry
     190     }
     191 
     192     /// <summary>
     193     /// 包含 Exception 事件数据的类
     194     /// </summary>
     195     public class ExceptionEventArgs : System.EventArgs
     196     {
     197         private System.Exception _Exception;
     198         private ExceptionActions _ExceptionAction;
     199 
     200         private DownLoadState _DownloadState;
     201 
     202         public DownLoadState DownloadState
     203         {
     204             get
     205             {
     206                 return _DownloadState;
     207             }
     208         }
     209 
     210         public Exception Exception
     211         {
     212             get
     213             {
     214                 return _Exception;
     215             }
     216         }
     217 
     218         public ExceptionActions ExceptionAction
     219         {
     220             get
     221             {
     222                 return _ExceptionAction;
     223             }
     224             set
     225             {
     226                 _ExceptionAction = value;
     227             }
     228         }
     229 
     230         internal ExceptionEventArgs(System.Exception e, DownLoadState DownloadState)
     231         {
     232             this._Exception = e;
     233             this._DownloadState = DownloadState;
     234         }
     235     }
     236 
     237     /// <summary>
     238     /// 包含 DownLoad 事件数据的类
     239     /// </summary>
     240     public class DownLoadEventArgs : System.EventArgs
     241     {
     242         private DownLoadState _DownloadState;
     243 
     244         public DownLoadState DownloadState
     245         {
     246             get
     247             {
     248                 return _DownloadState;
     249             }
     250         }
     251 
     252         public DownLoadEventArgs(DownLoadState DownloadState)
     253         {
     254             this._DownloadState = DownloadState;
     255         }
     256 
     257     }
     258 
     259     /// <summary>
     260     /// 支持断点续传多线程下载的类
     261     /// </summary>
     262     public class HttpWebClient
     263     {
     264         private static object _SyncLockObject = new object();
     265 
     266         public delegate void DataReceiveEventHandler(HttpWebClient Sender, DownLoadEventArgs e);
     267 
     268         public event DataReceiveEventHandler DataReceive; //接收字节数据事件
     269 
     270         public delegate void ExceptionEventHandler(HttpWebClient Sender, ExceptionEventArgs e);
     271 
     272         public event ExceptionEventHandler ExceptionOccurrs; //发生异常事件
     273 
     274         private int _FileLength; //下载文件的总大小
     275 
     276         public static ArrayList threads;
     277 
     278         public int FileLength
     279         {
     280             get
     281             {
     282                 return _FileLength;
     283             }
     284         }
     285 
     286         /// <summary>
     287         /// 分块下载文件
     288         /// </summary>
     289         /// <param name="Address">URL 地址</param>
     290         /// <param name="FileName">保存到本地的路径文件名</param>
     291         /// <param name="ChunksCount">块数,线程数</param>
     292         public void DownloadFile(string Address, string FileName, int ChunksCount)
     293         {
     294             int p = 0// position
     295             int s = 0// chunk size
     296             string a = null;
     297             HttpWebRequest hwrq;
     298             HttpWebResponse hwrp = null;
     299             try
     300             {
     301 
     302                 hwrq = (HttpWebRequest)WebRequest.Create(this.GetUri(Address));
     303                 //hwrq.Timeout = 20000000;
     304                 //if (hwrq.HaveResponse == false)
     305                 //    return;
     306                 //hwrq.ProtocolVersion =HttpVersion.Version10;
     307                 //WebProxy wp = WebProxy.GetDefaultProxy();
     308                 //hwrq.Proxy = wp;
     309                 hwrq.Method = "GET";
     310                 try
     311                 {
     312                     hwrp = (HttpWebResponse)hwrq.GetResponse();
     313                 }
     314                 catch (Exception e)
     315                 {
     316                     throw new Exception(e.Message);
     317                 }
     318 
     319                 long L = hwrp.ContentLength;
     320 
     321                 //如果文件太小, 就不用分多线程, 用一个线程下载即可. (目前控制在800K) 
     322                 //if (L < 800000)
     323                 //{
     324                 //    ChunksCount = 1;
     325                 //}
     326 
     327                 hwrq.Credentials = this.m_credentials;
     328 
     329                 L = ((L == -1|| (L > 0x7fffffff)) ? ((long)0x7fffffff) : L; //Int32.MaxValue 该常数的值为 2,147,483,647; 即十六进制的 0x7FFFFFFF
     330 
     331                 int l = (int)L;
     332 
     333                 this._FileLength = l;
     334 
     335                 bool b = (hwrp.Headers["Accept-Ranges"!= null & hwrp.Headers["Accept-Ranges"== "bytes");
     336                 a = hwrp.Headers["Content-Disposition"]; //attachment
     337                 if (a != null)
     338                 {
     339                     a = a.Substring(a.LastIndexOf("filename="+ 9);
     340                 }
     341                 else
     342                 {
     343                     a = FileName;
     344                 }
     345 
     346                 int ss = s;
     347                 if (b)
     348                 {
     349                     if (ExistControlFile(FileName)) //是否存在文件
     350                     {
     351                         string[] strBlocks = this.ReadInfFromControlFile(FileName).Split(new char[2] { '\r''\n' });
     352                         for (int i = 0; i < strBlocks.Length; i++)
     353                         {
     354                             if (strBlocks[i].Trim().Length != 0 && strBlocks[i].Substring(strBlocks[i].Length - 1== "0")
     355                             {
     356                                 string[] strRecord = strBlocks[i].Split(',');
     357                                 int p2 = int.Parse(strRecord[0]);
     358                                 int s2 = int.Parse(strRecord[1]);
     359                                 DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, p2, s2, new ThreadCallbackHandler(this.DownloadFileChunk));
     360                                 Thread t = new Thread(new ThreadStart(x.StartDownloadFileChunk));
     361                                 if (threads == null)
     362                                 {
     363                                     threads = new ArrayList();
     364                                 }
     365                                 threads.Add(t);
     366                                 t.Start();
     367                             }
     368 
     369 
     370                         }
     371 
     372                     }
     373                     else
     374                     {
     375                         //建立控制文件
     376                         FileStream fs = File.Create(this.GetControlFileName(FileName));
     377                         fs.Close();
     378 
     379                         if (File.Exists(FileName))
     380                         {
     381                             FileInfo fi = new FileInfo(FileName);
     382                             if (fi.Length == L)
     383                             {
     384                                 this.AddendInfToControlFile(FileName, 00);
     385                                 this.UpdateControlFile(FileName, 00);
     386                                 return;
     387                             }
     388                         }
     389 
     390                         s = l / ChunksCount;
     391                         if (s < 2 * 64 * 1024//块大小至少为 128 K 字节
     392                         {
     393                             s = 2 * 64 * 1024;
     394                         }
     395                         ss = s;
     396                         int i = 0;
     397                         while (l >= s)
     398                         {
     399                             l -= s;
     400                             if (l < s)
     401                             {
     402                                 s += l;
     403                             }
     404                             if (i++ > 0)
     405                             {
     406                                 DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, p, s, new ThreadCallbackHandler(this.DownloadFileChunk));
     407 
     408                                 AddendInfToControlFile(FileName, p, s);
     409                                 Thread t = new Thread(new ThreadStart(x.StartDownloadFileChunk));
     410                                 if (threads == null)
     411                                 {
     412                                     threads = new ArrayList();
     413                                 }
     414                                 threads.Add(t);
     415                                 t.Start();
     416 
     417                             }
     418                             p += s;
     419                         }
     420                         s = ss;
     421 
     422                         AddendInfToControlFile(FileName, 0, s);
     423                         DownLoadState x1 = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, 0, s, new ThreadCallbackHandler(this.DownloadFileChunk));
     424                         Thread t2 = new Thread(new ThreadStart(x1.StartDownloadFileChunk));
     425                         if (threads == null)
     426                         {
     427                             threads = new ArrayList();
     428                         }
     429                         threads.Add(t2);
     430                         t2.Start();
     431                     }
     432                 }
     433                 //如果服务器不支持断点续传(Accept-Range), 则使用单线程下载
     434                 else
     435                 {
     436                     AddendInfToControlFile(FileName, 0, l);
     437                     DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, 0, l, new ThreadCallbackHandler(this.DownloadFileChunk));
     438                     Thread t = new Thread(new ThreadStart(x.StartDownloadFileChunk));
     439                     if (threads == null)
     440                     {
     441                         threads = new ArrayList();
     442                     }
     443                     threads.Add(t);
     444                     t.Start();
     445                 }
     446             }
     447             catch (Exception e)
     448             {
     449                 //if (blnReturn == true)
     450                 //{
     451                 //    return;
     452                 //}
     453 
     454                 ExceptionActions ea = ExceptionActions.Throw;
     455                 if (ea == ExceptionActions.Throw)
     456                 {
     457                     if (!(e is WebException) && !(e is SecurityException))
     458                     {
     459                         throw new WebException("net_webclient", e);
     460                     }
     461                     throw;
     462                 }
     463 
     464 
     465                 //if (this.ExceptionOccurrs != null)
     466                 //{                    
     467                 //    DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, p, s);
     468 
     469                 //    ExceptionEventArgs eea = new ExceptionEventArgs(e, x);
     470                 //    ExceptionOccurrs(this, eea);
     471                 //    ea = eea.ExceptionAction;
     472                 //}
     473 
     474             }
     475 
     476         }

    477 
     478         #region 操作控制文件(By King Zheng)
     479 
     480         /// <summary>
     481         /// 插入文件块信息到控制文件(Add by ChengKing)
     482         /// </summary>
     483         /// <param name="FileName"></param>
     484         /// <param name="Position"></param>
     485         /// <param name="Length"></param>
     486         private void AddendInfToControlFile(string FileName, int Position, int Length)
     487         {
     488 
     489 
     490             try
     491             {
     492                 lock (_SyncLockObject)
     493                 {
     494                     string strControlFile = GetControlFileName(FileName);
     495 
     496 
     497                     //if (File.Exists(strControlFile) == false)
     498                     //{
     499                     //    return;
     500                     //}
     501 
     502                     using (StreamWriter sw = new StreamWriter(strControlFile, true, Encoding.Default))
     503                     {
     504                         //sw.NewLine = "$";
     505                         sw.WriteLine(Position.ToString() + "," + Length.ToString() + "," + "0");
     506                     }
     507                     //using (System.IO.FileStream sw = new System.IO.FileStream(strControlFile, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, System.IO.FileShare.ReadWrite))
     508                     //{
     509                     //    //sw.Position = e.DownloadState.Position;
     510                     //    sw.Write(Position.ToString() + "," + Length.ToString() + "," + "0"); 
     511                     //    sw.Close();
     512                     //}
     513 
     514 
     515 
     516                 }
     517             }
     518             catch (Exception e)
     519             {
     520                 throw new Exception("写控制文件出错!" + e.Message);
     521             }
     522 
     523         }
     524 
     525         /// <summary>
     526         /// 更新控制文件(Add by ChengKing)
     527         /// </summary>
     528         /// <param name="FileName"></param>
     529         /// <param name="Position"></param>
     530         /// <param name="Length"></param>
     531         private void UpdateControlFile(string FileName, int Position, int Length)
     532         {
     533             try
     534             {
     535                 lock (_SyncLockObject)
     536                 {
     537                     string strControlFile = GetControlFileName(FileName);
     538 
     539 
     540                     //if (File.Exists(strControlFile) == false)
     541                     //{
     542                     //    return;
     543                     //}
     544 
     545                     string s = null;
     546                     using (StreamReader sr = new System.IO.StreamReader(strControlFile))
     547                     {
     548                         s = sr.ReadToEnd();
     549                         s = s.Replace(Position.ToString() + "," + Length.ToString() + "," + "0", Position.ToString() + "," + Length.ToString() + "," + "1");
     550                     }
     551                     using (StreamWriter sw = new StreamWriter(strControlFile, false, Encoding.Default))
     552                     {
     553                         sw.WriteLine(s);
     554                     }
     555                 }
     556             }
     557             catch (Exception e)
     558             {
     559                 throw new Exception("更新控制文件出错!" + e.Message);
     560             }
     561 
     562         }
     563 
     564         /// <summary>
     565         /// 读取所有信息从控制文件(Add by ChengKing)
     566         /// </summary>
     567         /// <param name="FileName"></param>
     568         /// <returns></returns>
     569         private string ReadInfFromControlFile(string FileName)
     570         {
     571             try
     572             {
     573                 lock (_SyncLockObject)
     574                 {
     575                     string strControlFile = GetControlFileName(FileName);
     576 
     577                     string s = null;
     578                     using (StreamReader sr = new System.IO.StreamReader(strControlFile))
     579                     {
     580                         s = sr.ReadToEnd();
     581 
     582                     }
     583                     return s;
     584                 }
     585             }
     586             catch (Exception e)
     587             {
     588                 throw new Exception("读控制文件出错!" + e.Message);
     589             }
     590         }
     591 
     592         /// <summary>
     593         /// 根据目标文件名得到控制文件名(Add by ChengKing)
     594         /// </summary>
     595         /// <param name="FileName"></param>
     596         /// <returns></returns>
     597         public string GetControlFileName(string FileName)
     598         {
     599             string strPath = Path.GetDirectoryName(FileName);
     600 
     601             //string strFileNameWithoutExtension = Path.GetFileNameWithoutExtension(FileName);
     602             string strFileNameWithoutExtension = Path.GetFileName(FileName);
     603             string strControlFile = Path.Combine(strPath, strFileNameWithoutExtension + "_Control.txt");
     604             return strControlFile;
     605         }
     606 
     607         /// <summary>
     608         /// 判断控制文件是否存在
     609         /// </summary>
     610         /// <param name="FileName"></param>
     611         /// <returns></returns>
     612         private bool ExistControlFile(string FileName)
     613         {
     614             string strControlFile = GetControlFileName(FileName);
     615             if (File.Exists(strControlFile))
     616             {
     617                 return true;
     618             }
     619             return false;
     620         }
     621 
     622         /// <summary>
     623         /// 判断控制文件是否完成
     624         /// </summary>
     625         /// <param name="strControlFile"></param>
     626         /// <returns></returns>
     627         public bool JudgeControlFileIfFinished(string strControlFile)
     628         {
     629             try
     630             {
     631                 string s = null;
     632                 lock (_SyncLockObject)
     633                 {
     634                     using (StreamReader sr = new System.IO.StreamReader(strControlFile))
     635                     {
     636                         s = sr.ReadToEnd();
     637                     }
     638                 }
     639                 if (s + String.Empty == String.Empty)
     640                 {
     641                     return false;
     642                 }
     643                 string[] strBlocks = s.Split(new char[2] { '\r''\n' });
     644                 for (int i = 0; i < strBlocks.Length; i++)
     645                 {
     646                     if (strBlocks[i].Trim().Length != 0 && strBlocks[i].Substring(strBlocks[i].Length - 1== "0")
     647                     {
     648                         return false;
     649                     }
     650                 }
     651                 return true;
     652 
     653             }
     654             catch (Exception e)
     655             {
     656                 throw new Exception("判断控制文件是否完成时, 读取文件出错!" + e.Message);
     657             }
     658         }
    659 
     660         /// <summary>
     661         /// 删除控制文件(Add by ChengKing)
     662         /// </summary>
     663         /// <param name="strControlFile"></param>
     664         /// <returns></returns>
     665         public bool DeleteControlFile(string strControlFile)
     666         {
     667             try
     668             {
     669                 lock (_SyncLockObject)
     670                 {
     671                     if (File.Exists(strControlFile))
     672                     {
     673                         File.Delete(strControlFile);
     674                     }
     675                 }
     676                 return true;
     677             }
     678             catch (Exception e)
     679             {
     680                 throw new Exception("删除控制文件出错!" + e.Message);
     681             }
     682         }
     683 
     684         #endregion
     685 
     686         /// <summary>
     687         /// 下载一个文件块,利用该方法可自行实现多线程断点续传
     688         /// </summary>
     689         /// <param name="Address">URL 地址</param>
     690         /// <param name="FileName">保存到本地的路径文件名</param>
     691         /// <param name="Length">块大小</param>
     692         public void DownloadFileChunk(string Address, string FileName, int FromPosition, int Length)
     693         {
     694             HttpWebResponse hwrp = null;
     695             string a = null;
     696             try
     697             {
     698                 //this._FileName = FileName;
     699                 HttpWebRequest hwrq = (HttpWebRequest)WebRequest.Create(this.GetUri(Address));
     700                 //hwrq.Credentials = this.m_credentials;
     701 
     702                 hwrq.AddRange(FromPosition);
     703 
     704                 hwrp = (HttpWebResponse)hwrq.GetResponse();
     705 
     706                 //hwrp.Headers.Add("Content-Range", FromPosition.ToString());  //Test
     707 
     708                 a = hwrp.Headers["Content-Disposition"]; //attachment
     709                 if (a != null)
     710                 {
     711                     a = a.Substring(a.LastIndexOf("filename="+ 9);
     712                 }
     713                 else
     714                 {
     715                     a = FileName;
     716                 }
     717 
     718                 byte[] buffer = this.ResponseAsBytes(Address, hwrp, Length, FileName);
     719                 //   lock (_SyncLockObject)
     720                 //   {
     721                 //    this._Bytes += buffer.Length;
     722                 //   }
     723             }
     724             catch (Exception e)
     725             {
     726                 ExceptionActions ea = ExceptionActions.Throw;
     727                 if (this.ExceptionOccurrs != null)
     728                 {
     729                     DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, FromPosition, Length);
     730                     ExceptionEventArgs eea = new ExceptionEventArgs(e, x);
     731                     ExceptionOccurrs(this, eea);
     732                     ea = eea.ExceptionAction;
     733                 }
     734 
     735                 if (ea == ExceptionActions.Throw)
     736                 {
     737                     if (!(e is WebException) && !(e is SecurityException))
     738                     {
     739                         throw new WebException("net_webclient", e);
     740                     }
     741                     throw;
     742                 }
     743             }
     744         }
     745 
     746         internal byte[] ResponseAsBytes(string RequestURL, WebResponse Response, long Length, string FileName)
     747         {
     748             string a = null//AttachmentName
     749             int P = 0//整个文件的位置指针
     750             int num2 = 0;
     751             int num3 = 0;
     752             int intFrom = 0;
     753             try
     754             {
     755                 a = Response.Headers["Content-Disposition"]; //attachment
     756                 if (a != null)
     757                 {
     758                     a = a.Substring(a.LastIndexOf("filename="+ 9);
     759                 }
     760 
     761                 long num1 = Length; //Response.ContentLength;
     762                 bool flag1 = false;
     763                 if (num1 == -1)
     764                 {
     765                     flag1 = true;
     766                     num1 = 0x10000//64k
     767                 }
     768                 byte[] buffer1 = new byte[(long)num1];
     769 
     770 
     771                 int p = 0//本块的位置指针
     772 
     773                 string s = Response.Headers["Content-Range"];
     774                 //string s = hwrq.Headers["Range"];
     775 
     776                 if (s != null)
     777                 {
     778                     s = s.Replace("bytes """);
     779                     s = s.Substring(0, s.IndexOf("-"));
     780                     P = Convert.ToInt32(s);
     781                     intFrom = P;
     782 
     783                 }
     784 
     785                 //int num3 = 0;
     786 
     787                 Stream S = Response.GetResponseStream();
     788 
     789                 int count = 0;
     790 
     791                 int bufferSize = 65535//允许读取的最大字节
     792 
     793                 int times;
     794                 do
     795                 {
     796                     times = 0;
     797 
     798                     //num2 = S.Read(buffer1, num3, ((int)num1) - num3);
     799 
     800                     //限制最大读取字节
     801                     if (bufferSize < ((int)num1) - num3)
     802                     {
     803                         num2 = S.Read(buffer1, num3, bufferSize);
     804                     }
     805                     else
     806                     {
     807                         num2 = S.Read(buffer1, num3, ((int)num1) - num3);
     808                     }
     809 
     810                     //网络短时间的不稳定
     811                     if (num2 == 0)
     812                     {
     813                         Thread.Sleep(50);
     814                         times++;
     815 
     816                         if (times > 100)
     817                         {
     818                             throw new Exception("网络传输层错误");
     819                         }
     820 
     821                     }
     822 
     823                     num3 += num2;
     824                     if (flag1 && (num3 == num1))
     825                     {
     826                         num1 += 0x10000;
     827                         byte[] buffer2 = new byte[(int)num1];
     828                         Buffer.BlockCopy(buffer1, 0, buffer2, 0, num3);
     829                         buffer1 = buffer2;
     830                     }
     831 
     832                     //    lock (_SyncLockObject)
     833                     //    {
     834                     //     this._bytes += num2;
     835                     //    }
     836                     if (num2 > 0)
     837                     {
     838                         if (this.DataReceive != null)
     839                         {
     840                             byte[] buffer = new byte[num2];
     841                             Buffer.BlockCopy(buffer1, p, buffer, 0, buffer.Length);
     842                             DownLoadState dls = new DownLoadState(RequestURL, Response.ResponseUri.AbsolutePath, FileName, a, P, num2, buffer);
     843                             DownLoadEventArgs dlea = new DownLoadEventArgs(dls);
     844 
     845                             //触发事件
     846                             this.OnDataReceive(dlea);
     847                             //System.Threading.Thread.Sleep(100);                            
     848 
     849                         }
     850                         p += num2; //本块的位置指针
     851                         P += num2; //整个文件的位置指针
     852                     }
     853                     else
     854                     {
     855                         break;
     856                     }
     857 
     858                 }
     859                 while (num2 != 0);
     860 
     861                 count++;
     862 
     863                 int c = count;
     864 
     865                 S.Close();
     866                 S = null;
     867                 if (flag1)
     868                 {
     869                     byte[] buffer3 = new byte[num3];
     870                     Buffer.BlockCopy(buffer1, 0, buffer3, 0, num3);
     871                     buffer1 = buffer3;
     872                 }
     873 
     874                 UpdateControlFile(FileName, intFrom, (int)Length);
     875 
     876                 return buffer1;
     877             }
     878             catch (Exception e)
     879             {
     880                 ExceptionActions ea = ExceptionActions.Throw;
     881                 if (this.ExceptionOccurrs != null)
     882                 {
     883                     Thread.Sleep(100);
     884                     //DownLoadState x = new DownLoadState(RequestURL, Response.ResponseUri.AbsolutePath, FileName, a, P, num2);
     885                     //DownLoadState x = new DownLoadState(RequestURL, Response.ResponseUri.AbsolutePath, FileName, a, P, (int)(Length - num3));
     886                     DownLoadState x = new DownLoadState(RequestURL, Response.ResponseUri.AbsolutePath, FileName, a, P, (int)Length);
     887 
     888                     ExceptionEventArgs eea = new ExceptionEventArgs(e, x);
     889                     ExceptionOccurrs(this, eea);
     890                     ea = eea.ExceptionAction;
     891                 }
     892 
     893                 if (ea == ExceptionActions.Throw)
     894                 {
     895                     if (!(e is WebException) && !(e is SecurityException))
     896                     {
     897                         throw new WebException("net_webclient", e);
     898                     }
     899                     throw;
     900                 }
     901                 return null;
     902             }
     903         }

    904 
     905         private void OnDataReceive(DownLoadEventArgs e)
     906         {
     907             //触发数据到达事件
     908             DataReceive(this, e);
     909         }
     910 
     911         public byte[] UploadFile(string address, string fileName)
     912         {
     913             return this.UploadFile(address, "POST", fileName, "file");
     914         }
     915 
     916         public string UploadFileEx(string address, string method, string fileName, string fieldName)
     917         {
     918             return Encoding.ASCII.GetString(UploadFile(address, method, fileName, fieldName));
     919         }
     920 
     921         public byte[] UploadFile(string address, string method, string fileName, string fieldName)
     922         {
     923             byte[] buffer4;
     924             FileStream stream1 = null;
     925             try
     926             {
     927                 fileName = Path.GetFullPath(fileName);
     928                 string text1 = "---------------------" + DateTime.Now.Ticks.ToString("x");
     929 
     930                 string text2 = "application/octet-stream";
     931 
     932                 stream1 = new FileStream(fileName, FileMode.Open, FileAccess.Read);
     933                 WebRequest request1 = WebRequest.Create(this.GetUri(address));
     934                 request1.Credentials = this.m_credentials;
     935                 request1.ContentType = "multipart/form-data; boundary=" + text1;
     936 
     937                 request1.Method = method;
     938                 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" };
     939                 string text3 = string.Concat(textArray1);
     940                 byte[] buffer1 = Encoding.UTF8.GetBytes(text3);
     941                 byte[] buffer2 = Encoding.ASCII.GetBytes("\r\n--" + text1 + "\r\n");
     942                 long num1 = 0x7fffffffffffffff;
     943                 try
     944                 {
     945                     num1 = stream1.Length;
     946                     request1.ContentLength = (num1 + buffer1.Length) + buffer2.Length;
     947                 }
     948                 catch
     949                 {
     950                 }
     951                 byte[] buffer3 = new byte[Math.Min(0x2000, (int)num1)];
     952                 using (Stream stream2 = request1.GetRequestStream())
     953                 {
     954                     int num2;
     955                     stream2.Write(buffer1, 0, buffer1.Length);
     956                     do
     957                     {
     958                         num2 = stream1.Read(buffer3, 0, buffer3.Length);
     959                         if (num2 != 0)
     960                         {
     961                             stream2.Write(buffer3, 0, num2);
     962                         }
     963                     }
     964                     while (num2 != 0);
     965                     stream2.Write(buffer2, 0, buffer2.Length);
     966                 }
     967                 stream1.Close();
     968                 stream1 = null;
     969                 WebResponse response1 = request1.GetResponse();
     970 
     971                 buffer4 = this.ResponseAsBytes(response1);
     972             }
     973             catch (Exception exception1)
     974             {
     975                 if (stream1 != null)
     976                 {
     977                     stream1.Close();
     978                     stream1 = null;
     979                 }
     980                 if (!(exception1 is WebException) && !(exception1 is SecurityException))
     981                 {
     982                     //throw new WebException(SR.GetString("net_webclient"), exception1);
     983                     throw new WebException("net_webclient", exception1);
     984                 }
     985                 throw;
     986             }
     987             return buffer4;
     988         }
     989 

    990         private byte[] ResponseAsBytes(WebResponse response)
     991         {
     992             int num2;
     993             long num1 = response.ContentLength;
     994             bool flag1 = false;
     995             if (num1 == -1)
     996             {
     997                 flag1 = true;
     998                 num1 = 0x10000;
     999             }
    1000             byte[] buffer1 = new byte[(int)num1];
    1001             Stream stream1 = response.GetResponseStream();
    1002             int num3 = 0;
    1003             do
    1004             {
    1005                 num2 = stream1.Read(buffer1, num3, ((int)num1) - num3);
    1006                 num3 += num2;
    1007                 if (flag1 && (num3 == num1))
    1008                 {
    1009                     num1 += 0x10000;
    1010                     byte[] buffer2 = new byte[(int)num1];
    1011                     Buffer.BlockCopy(buffer1, 0, buffer2, 0, num3);
    1012                     buffer1 = buffer2;
    1013                 }
    1014             }
    1015             while (num2 != 0);
    1016             stream1.Close();
    1017             if (flag1)
    1018             {
    1019                 byte[] buffer3 = new byte[num3];
    1020                 Buffer.BlockCopy(buffer1, 0, buffer3, 0, num3);
    1021                 buffer1 = buffer3;
    1022             }
    1023             return buffer1;
    1024         }
    1025 
    1026         private NameValueCollection m_requestParameters;
    1027         private Uri m_baseAddress;
    1028         private ICredentials m_credentials = CredentialCache.DefaultCredentials;
    1029 
    1030         public ICredentials Credentials
    1031         {
    1032             get
    1033             {
    1034                 return this.m_credentials;
    1035             }
    1036             set
    1037             {
    1038                 this.m_credentials = value;
    1039             }
    1040         }
    1041 
    1042         public NameValueCollection QueryString
    1043         {
    1044             get
    1045             {
    1046                 if (this.m_requestParameters == null)
    1047                 {
    1048                     this.m_requestParameters = new NameValueCollection();
    1049                 }
    1050                 return this.m_requestParameters;
    1051             }
    1052             set
    1053             {
    1054                 this.m_requestParameters = value;
    1055             }
    1056         }
    1057 
    1058         public string BaseAddress
    1059         {
    1060             get
    1061             {
    1062                 if (this.m_baseAddress != null)
    1063                 {
    1064                     return this.m_baseAddress.ToString();
    1065                 }
    1066                 return string.Empty;
    1067             }
    1068             set
    1069             {
    1070                 if ((value == null|| (value.Length == 0))
    1071                 {
    1072                     this.m_baseAddress = null;
    1073                 }
    1074                 else
    1075                 {
    1076                     try
    1077                     {
    1078                         this.m_baseAddress = new Uri(value);
    1079                     }
    1080                     catch (Exception exception1)
    1081                     {
    1082                         throw new ArgumentException("value", exception1);
    1083                     }
    1084                 }
    1085             }
    1086         }
    1087 
    1088         public Uri GetUri(string path)
    1089         {
    1090             Uri uri1;
    1091             try
    1092             {
    1093                 if (this.m_baseAddress != null)
    1094                 {
    1095                     uri1 = new Uri(this.m_baseAddress, path);
    1096                 }
    1097                 else
    1098                 {
    1099                     uri1 = new Uri(path);
    1100                 }
    1101                 if (this.m_requestParameters == null)
    1102                 {
    1103                     return uri1;
    1104                 }
    1105                 StringBuilder builder1 = new StringBuilder();
    1106                 string text1 = string.Empty;
    1107                 for (int num1 = 0; num1 < this.m_requestParameters.Count; num1++)
    1108                 {
    1109                     builder1.Append(text1 + this.m_requestParameters.AllKeys[num1] + "=" + this.m_requestParameters[num1]);
    1110                     text1 = "&";
    1111                 }
    1112                 UriBuilder builder2 = new UriBuilder(uri1);
    1113                 builder2.Query = builder1.ToString();
    1114                 uri1 = builder2.Uri;
    1115             }
    1116             catch (UriFormatException)
    1117             {
    1118                 uri1 = new Uri(Path.GetFullPath(path));
    1119             }
    1120             return uri1;
    1121         }
    1122 
    1123     }
    1124 
    1125 }
    1126 
    1127 

        2.页面 Default.aspx 文件 代码

     1 <html xmlns="http://www.w3.org/1999/xhtml" >
     2 <head runat="server">
     3     <script language="javascript">
     4         mainLoop = function()
     5         {
     6             var objPath = document.getElementById("TextBox2"); 
     7             var blnValue = _Default.CheckControlFiles(objPath.value);                       
     8             //a.value = a.value + blnValue.value;
     9             if( blnValue.value == true)
    10             {
    11                 var returnvalue=setTimeout('mainLoop()'1000);            
    12             }
    13             else
    14             {
    15                 var objStatus = document.getElementById("Label1"); 
    16                 objStatus.innerText = "状态: 下载完成!";
    17                 
    18                 var btOK = document.getElementById("btOK");
    19                 btOK.disabled = "";              
    20                 
    21                 var btCancel = document.getElementById("btCancel");
    22                 btCancel.disabled = "disabled";
    23                                 
    24             }
    25         }    
    26         
    27     
    28     </script>
    29 
    30 </head>
    31 <body>
    32     <form id="frmTest" runat="server" >
    33     <table bgcolor="#ffcc66"><tr><td style="height: 259px">
    34         <br />
    35         <strong><span style="color: #000099">
    36         下载组件:
    37         <br />
    38         1. 支持多线程: &nbsp;多个线程某时刻下载同一个文件的不同块.<br />
    39         2. 断点续传: &nbsp;如果下载了一个文件的某些块(一半), 则下次<br />
    40             &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 下载时只需下载未完成的块;
    41             &nbsp;文件块的下载状<br />
    42             &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 态用控制文件记录.
    43             块下载完成的先后顺序不<br />
    44             &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 一定是连续的.<br />
    45         </span></strong>
    46         <br />
    47         <table style=" 379px">
    48             <tr>
    49                 <td colspan="1" style=" 87px">
    50                     Source</td>
    51                 <td colspan="2" style=" 326px">
    52         <asp:TextBox ID="TextBox1" runat="server" Width="391px">http://www.</asp:TextBox></td>
    53             </tr>
    54             <tr>
    55                 <td colspan="1" style=" 87px">
    56                     Location</td>
    57                 <td colspan="2" style=" 326px">
    58                     <asp:TextBox ID="TextBox2" runat="server" Width="391px">D:\Documents and Settings\zhengjian\桌面\TestDownLoads\</asp:TextBox></td>
    59             </tr>
    60             <tr>
    61                 <td colspan="1" style=" 87px">
    62                     Threads</td>
    63                 <td colspan="2" style=" 326px">
    64                     <asp:TextBox ID="TextBox3" runat="server" Width="390px">10</asp:TextBox></td>
    65             </tr>
    66         </table>
    67         <br />
    68         <asp:Button ID="btOK" runat="server" Text="下载" Height="42px" Width="108px" OnClick="btOK_Click" />&nbsp;
    69         &nbsp;<asp:Button ID="btCancel" runat="server" OnClick="btCancel_Click" Text="取消/暂停" Height="42px" Width="108px" Enabled="False" /><br />
    70         <br />
    71         <asp:Label ID="Label1" runat="server" Height="32px" Text="状态: 未开始下载" Width="227px" Font-Bold="True" ForeColor="#8080FF"></asp:Label><br />
    72         </td></tr></table>
    73         <script language=javascript>
    74             mainLoop();
    75         </script>
    76     </form>
    77 </body>
    78 </html>

       3. 页面后台文件 Default.aspx.cs代码

      1 /// <summary>
      2 /// Author: [ ChengKing(ZhengJian) ] 
      3 /// Blog:   Http://blog.csdn.net/ChengKing
      4 /// 注:从网上找了个优秀代码
      5 /// 扩展如下功能: 
      6 ///   1. 解决一些线程相关的Bug; 
      7 ///   2.扩展用控制文件实现断点续传功能.
      8 /// </summary>
      9 public partial class _Default : System.Web.UI.Page 
     10 {    
     11     //全局变量
     12     private static object _SyncLockObject = new object();
     13 
     14     protected void Page_Load(object sender, EventArgs e)
     15     {
     16         Utility.RegisterTypeForAjax(typeof(_Default));       
     17         //this.TextBox1.Text = "http://download.csdn.net/filedown/aHR0cDovL2Rvd25sb2FkMS5jc2RuLm5ldC9kb3duMy8yMDA3MDUwNy8wNzE4MDIwNzY4OC5yYXI=!177258";
     18         
     19         
     20         this.TextBox1.Text = "https://files.cnblogs.com/ChengKing/智能象棋游戏(T1).rar";
     21     }
     22     protected void btOK_Click(object sender, EventArgs e)
     23     {
     24         this.Label1.Text = "状态: 正在下载";
     25         
     26         DownLoadComponent.HttpWebClient x = new DownLoadComponent.HttpWebClient();
     27 
     28         //注册 DataReceive 事件
     29         x.DataReceive += new DownLoadComponent.HttpWebClient.DataReceiveEventHandler(this.x_DataReceive);
     30         //注册 ExceptionOccurrs 事件
     31         x.ExceptionOccurrs += new DownLoadComponent.HttpWebClient.ExceptionEventHandler(this.x_ExceptionOccurrs);
     32 
     33         string Source = this.TextBox1.Text.Trim();
     34         string FileName = Source.Substring(Source.LastIndexOf("/"+ 1);
     35         string Location= System.IO.Path.Combine( this.TextBox2.Text.Trim() , FileName);
     36         
     37         //F: 源服务器文件;  _f: 保存路径;  10: 自设定一个文件有几个线程下载.
     38         x.DownloadFile(Source,Location , int.Parse(this.TextBox3.Text));
     39 
     40         //Response.Write("正在下载文件");
     41         this.btOK.Enabled = false;
     42         this.btCancel.Enabled = true;
     43     }
     44 
     45     private void x_DataReceive(DownLoadComponent.HttpWebClient Sender, DownLoadComponent.DownLoadEventArgs e)
     46     {
     47 
     48         string f = e.DownloadState.FileName;
     49         if (e.DownloadState.AttachmentName != null)
     50             f = System.IO.Path.GetDirectoryName(f) + @"\" + e.DownloadState.AttachmentName;       
     51         
     52         using (System.IO.FileStream sw = new System.IO.FileStream(f, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite, System.IO.FileShare.ReadWrite))
     53         {
     54             sw.Position = e.DownloadState.Position;                
     55             sw.Write(e.DownloadState.Data, 0, e.DownloadState.Data.Length); 
     56             sw.Close();
     57         }            
     58     }   
     59 
     60     private void x_ExceptionOccurrs(DownLoadComponent.HttpWebClient Sender, DownLoadComponent.ExceptionEventArgs e)
     61     {
     62         System.Console.WriteLine(e.Exception.Message);
     63         //发生异常重新下载相当于断点续传,你可以自己自行选择处理方式或自行处理
     64         DownLoadComponent.HttpWebClient x = new DownLoadComponent.HttpWebClient();
     65         x.DataReceive += new DownLoadComponent.HttpWebClient.DataReceiveEventHandler(this.x_DataReceive);
     66         //订阅 ExceptionOccurrs 事件
     67         //x.ExceptionOccurrs += new DownLoadComponent.HttpWebClient.ExceptionEventHandler(this.x_ExceptionOccurrs);
     68 
     69         x.DownloadFileChunk(e.DownloadState.RequestURL, e.DownloadState.FileName, e.DownloadState.Position, e.DownloadState.Length);
     70         e.ExceptionAction = DownLoadComponent.ExceptionActions.Ignore;
     71     }
     72     protected void btCancel_Click(object sender, EventArgs e)
     73     {
     74         if (DownLoadComponent.HttpWebClient.threads != null)
     75         {
     76             foreach (Thread t in DownLoadComponent.HttpWebClient.threads)
     77             {
     78                 if (t.IsAlive)
     79                 {
     80                     t.Abort();
     81                 }
     82             }
     83 
     84             DownLoadComponent.HttpWebClient.threads.Clear();
     85         }
     86         System.Diagnostics.Process myproc = new System.Diagnostics.Process();
     87         Process[] procs = (Process[])Process.GetProcessesByName("DW20.exe");  //得到所有打开的进程
     88         try
     89         {
     90             foreach (Process proc in procs)
     91             {
     92                 if (proc.CloseMainWindow() == false)
     93                 {
     94                     proc.Kill();
     95                 }
     96             }
     97         }
     98         catch
     99         { }
    100         KillAllThreads();
    101         this.btOK.Enabled = true;
    102         this.btCancel.Enabled = false;
    103         GC.Collect();
    104        
    105     }
    106 
    107     /// <summary>
    108     /// 定期检查控制文件
    109     /// </summary>
    110     /// <param name="str"></param>
    111     /// <returns>是否还继续监视(1: 正在下载中,继续监视; 0: 表示已经下载完毕,不用再检视)</returns>
    112     [AjaxMethod()]// or [AjaxPro.AjaxMethod] 
    113     public bool CheckControlFiles(string strObjPath)
    114     {
    115         if (!WhetherDownloadFinished(strObjPath))
    116         {
    117             return true;
    118         }
    119         return false;
    120     }
    121 
    122     private bool WhetherDownloadFinished(string strObjPath)
    123     {
    124         DirectoryInfo df = new DirectoryInfo(strObjPath);
    125         FileInfo[] fi = (FileInfo[])df.GetFiles("*.txt", SearchOption.TopDirectoryOnly);
    126         HttpWebClient hwc = new HttpWebClient();        
    127         for (int i = 0; i < fi.Length; i++)
    128         {
    129             if (fi[i].FullName.Length > 12 && fi[i].FullName.Substring(fi[i].FullName.Length - 12== "_Control.txt")
    130             {                
    131                 if (hwc.JudgeControlFileIfFinished(fi[i].FullName) == true)
    132                 {
    133                     hwc.DeleteControlFile(fi[i].FullName);
    134                     KillAllThreads();
    135                     return true;
    136                 }
    137             }
    138         }
    139         return false;
    140     }
    141 
    142     private void KillAllThreads()
    143     {
    144         foreach (Thread t in HttpWebClient.threads)
    145         {
    146             if (t.IsAlive)
    147             {
    148                 t.Abort();
    149             }
    150         }
    151         HttpWebClient.threads.Clear();
    152     }
    153 
    154 }
    155 

    (四).示例代码下载

           https://files.cnblogs.com/MVP33650/MultiThreadDownLoadFile.rar

    (五).Asp.net 2.0其它相关文章:     

               http://blog.csdn.net/ChengKing/category/288694.aspx

  • 相关阅读:
    报错:maven 程序包org.junit不存在
    Sublime Text 3
    Win10使用技巧
    CookieHelper
    log4net
    文件导出 Aspose
    C# 数字证书加载 X509Certificate2
    前后端文件上传
    WebApi 后端文件传输至远程服务器
    aspnet_regiis.exe用法(备忘非自创)
  • 原文地址:https://www.cnblogs.com/hdjjun/p/1223891.html
Copyright © 2011-2022 走看看