【夜战鹰】【ChengKing(ZhengJian)】

【夜战鹰】【ChengKing(ZhengJian)】

博客园 首页 联系 订阅 管理

(一) . 概述

        最近做了个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="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 2008-04-05 18:57  【ChengKing(ZhengJian)】  阅读(976)  评论(1编辑  收藏  举报