ms_dos

  博客园  :: 首页  :: 新随笔  ::  :: 订阅 订阅  :: 管理

(一) . 概述

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

许多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="width: 379px">
48             <tr>
49                 <td colspan="1" style="width: 87px">
50                     Source</td>
51                 <td colspan="2" style="width: 326px">
52         <asp:TextBox ID="TextBox1" runat="server" Width="391px">http://www.</asp:TextBox></td>
53             </tr>
54             <tr>
55                 <td colspan="1" style="width: 87px">
56                     Location</td>
57                 <td colspan="2" style="width: 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="width: 87px">
62                     Threads</td>
63                 <td colspan="2" style="width: 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

posted on 2007-06-22 11:16  ms_dos  阅读(400)  评论(0编辑  收藏  举报