Asp.net 2.0 文件下载[支持多线程, 断点续传功能](示例代码下载)

(一) . 概述

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

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

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

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

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

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

              

(二).运行效果

Asp.net 2.0 文件下载[支持多线程, 断点续传功能](示例代码下载)_第1张图片

 (三). 代码

  1. 核心 DownLoadState.cs 文件代码

   1  ///  
   2  ///  Author: [ ChengKing(ZhengJian) ] 
   3  ///  Blog:   Http://blog.csdn.net/ChengKing
   4  ///  注:从网上找了个优秀代码
   5  ///  扩展如下功能: 
   6  ///    1. 解决一些线程相关的Bug; 
   7  ///    2.扩展用控制文件实现断点续传功能.
   8  ///  

   9  namespace  DownLoadComponent
  10  {
  11       ///  
  12       ///  多线程辅助类(Add by ChengKing)
  13       ///  

  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       ///  
  63       ///  记录下载的字节位置
  64       ///  

  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       ///  
 193       ///  包含 Exception 事件数据的类
 194       ///  

 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       ///  
 238       ///  包含 DownLoad 事件数据的类
 239       ///  

 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       ///  
 260       ///  支持断点续传多线程下载的类
 261       ///  

 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           ///  
 287           ///  分块下载文件
 288           ///  

 289           ///   URL 地址
 290           ///   保存到本地的路径文件名
 291           ///   块数,线程数
 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,  0 0 );
 385                                   this .UpdateControlFile(FileName,  0 0 );
 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         /// 


 481         /// 插入文件块信息到控制文件(Add by ChengKing)
 482         /// 

 483         /// 
 484         /// 
 485         /// 
 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         /// 
 526         /// 更新控制文件(Add by ChengKing)
 527         /// 

 528         /// 
 529         /// 
 530         /// 
 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         /// 
 565         /// 读取所有信息从控制文件(Add by ChengKing)
 566         /// 

 567         /// 
 568         /// 
 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         /// 
 593         /// 根据目标文件名得到控制文件名(Add by ChengKing)
 594         /// 

 595         /// 
 596         /// 
 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         /// 
 608         /// 判断控制文件是否存在
 609         /// 

 610         /// 
 611         /// 
 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         /// 
 623         /// 判断控制文件是否完成
 624         /// 

 625         /// 
 626         /// 
 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         /// 
 661         /// 删除控制文件(Add by ChengKing)
 662         /// 

 663         /// 
 664         /// 
 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         /// 
 687         /// 下载一个文件块,利用该方法可自行实现多线程断点续传
 688         /// 

 689         /// URL 地址
 690         /// 保存到本地的路径文件名
 691         /// 块大小
 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.
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  ///  
  2  ///  Author: [ ChengKing(ZhengJian) ] 
  3  ///  Blog:   Http://blog.csdn.net/ChengKing
  4  ///  注:从网上找了个优秀代码
  5  ///  扩展如下功能: 
  6  ///    1. 解决一些线程相关的Bug; 
  7  ///    2.扩展用控制文件实现断点续传功能.
  8  ///  

  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  =   " http://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       ///  
108       ///  定期检查控制文件
109       ///  

110       ///  
111       ///   是否还继续监视(1: 正在下载中,继续监视; 0: 表示已经下载完毕,不用再检视)
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 

 

(四).示例代码下载

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

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

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

转载于:https://www.cnblogs.com/hdjjun/archive/2008/06/17/1223891.html

你可能感兴趣的:(Asp.net 2.0 文件下载[支持多线程, 断点续传功能](示例代码下载))