C#断点续传
View Code
1 using System; 2 using System.IO; 3 using System.Net; 4 using System.Text; 5 using System.Security; 6 using System.Threading; 7 using System.Collections.Specialized; 8 using Sort; 9 10 namespace Sort 11 { 12 // <summary> 13 /// 记录下载的字节位置 14 /// </summary> 15 public class DownLoadState 16 { 17 private string _FileName; 18 19 private string _AttachmentName; 20 private int _Position; 21 private string _RequestURL; 22 private string _ResponseURL; 23 private int _Length; 24 25 private byte[] _Data; 26 27 /// <summary> 28 /// 文件名 29 /// </summary> 30 public string FileName 31 { 32 get 33 { 34 return _FileName; 35 } 36 } 37 38 /// <summary> 39 /// 下载的位置 40 /// </summary> 41 public int Position 42 { 43 get 44 { 45 return _Position; 46 } 47 } 48 49 /// <summary> 50 /// 数据长度 51 /// </summary> 52 public int Length 53 { 54 get 55 { 56 return _Length; 57 } 58 } 59 60 /// <summary> 61 /// 附件名称 62 /// </summary> 63 public string AttachmentName 64 { 65 get 66 { 67 return _AttachmentName; 68 } 69 } 70 71 /// <summary> 72 /// 请求URL 73 /// </summary> 74 public string RequestURL 75 { 76 get 77 { 78 return _RequestURL; 79 } 80 } 81 82 /// <summary> 83 /// 响应URL 84 /// </summary> 85 public string ResponseURL 86 { 87 get 88 { 89 return _ResponseURL; 90 } 91 } 92 93 /// <summary> 94 /// 数据 95 /// </summary> 96 public byte[] Data 97 { 98 get 99 { 100 return _Data; 101 } 102 } 103 104 internal DownLoadState(string RequestURL, string ResponseURL, string FileName, string AttachmentName, int Position, int Length, byte[] Data) 105 { 106 this._FileName = FileName; 107 this._RequestURL = RequestURL; 108 this._ResponseURL = ResponseURL; 109 this._AttachmentName = AttachmentName; 110 this._Position = Position; 111 this._Data = Data; 112 this._Length = Length; 113 } 114 115 //ThreadCallbackHandler 回调事件,自动执行该方法 116 internal DownLoadState(string RequestURL, string ResponseURL, string FileName, string AttachmentName, int Position, int Length, ThreadCallbackHandler tch) 117 { 118 this._RequestURL = RequestURL; 119 this._ResponseURL = ResponseURL; 120 this._FileName = FileName; 121 this._AttachmentName = AttachmentName; 122 this._Position = Position; 123 this._Length = Length; 124 this._ThreadCallback = tch; 125 } 126 127 internal DownLoadState(string RequestURL, string ResponseURL, string FileName, string AttachmentName, int Position, int Length) 128 { 129 this._RequestURL = RequestURL; 130 this._ResponseURL = ResponseURL; 131 this._FileName = FileName; 132 this._AttachmentName = AttachmentName; 133 this._Position = Position; 134 this._Length = Length; 135 } 136 137 private ThreadCallbackHandler _ThreadCallback; 138 139 public HttpWebClient httpWebClient 140 { 141 get 142 { 143 return this._hwc; 144 } 145 set 146 { 147 this._hwc = value; 148 } 149 } 150 151 internal Thread thread 152 { 153 get 154 { 155 return _thread; 156 } 157 set 158 { 159 _thread = value; 160 } 161 } 162 163 private HttpWebClient _hwc; 164 private Thread _thread; 165 166 // 167 internal void StartDownloadFileChunk() 168 { 169 if (this._ThreadCallback != null) 170 { 171 this._ThreadCallback(this._RequestURL, this._FileName, this._Position, this._Length); 172 this._hwc.OnThreadProcess(this._thread); 173 } 174 } 175 } 176 177 //委托代理线程的所执行的方法签名一致 178 public delegate void ThreadCallbackHandler(string S, string s, int I, int i); 179 180 /// <summary> 181 /// 异常处理动作 182 /// </summary> 183 public enum ExceptionActions 184 { 185 Throw, 186 CancelAll, 187 Ignore, 188 Retry 189 } 190 191 /// <summary> 192 /// 包含 Exception 事件数据的类 193 /// </summary> 194 public class ExceptionEventArgs : System.EventArgs 195 { 196 private System.Exception _Exception; 197 private ExceptionActions _ExceptionAction; 198 199 private DownLoadState _DownloadState; 200 201 public DownLoadState DownloadState 202 { 203 get 204 { 205 return _DownloadState; 206 } 207 } 208 209 public Exception Exception 210 { 211 get 212 { 213 return _Exception; 214 } 215 } 216 217 public ExceptionActions ExceptionAction 218 { 219 get 220 { 221 return _ExceptionAction; 222 } 223 set 224 { 225 _ExceptionAction = value; 226 } 227 } 228 229 internal ExceptionEventArgs(System.Exception e, DownLoadState DownloadState) 230 { 231 this._Exception = e; 232 this._DownloadState = DownloadState; 233 } 234 } 235 236 /// <summary> 237 /// 包含 DownLoad 事件数据的类 238 /// </summary> 239 public class DownLoadEventArgs : System.EventArgs 240 { 241 private DownLoadState _DownloadState; 242 243 public DownLoadState DownloadState 244 { 245 get 246 { 247 return _DownloadState; 248 } 249 } 250 251 public DownLoadEventArgs(DownLoadState DownloadState) 252 { 253 this._DownloadState = DownloadState; 254 } 255 256 } 257 258 public class ThreadProcessEventArgs : System.EventArgs 259 { 260 private Thread _thread; 261 262 public Thread thread 263 { 264 get 265 { 266 return this._thread; 267 } 268 } 269 270 public ThreadProcessEventArgs(Thread thread) 271 { 272 this._thread = thread; 273 } 274 275 } 276 277 /// <summary> 278 /// 支持断点续传多线程下载的类 279 /// </summary> 280 public class HttpWebClient 281 { 282 private static object _SyncLockObject = new object(); 283 284 public delegate void DataReceiveEventHandler(HttpWebClient Sender, DownLoadEventArgs e); 285 286 public event DataReceiveEventHandler DataReceive; //接收字节数据事件 287 288 public delegate void ExceptionEventHandler(HttpWebClient Sender, ExceptionEventArgs e); 289 290 public event ExceptionEventHandler ExceptionOccurrs; //发生异常事件 291 292 public delegate void ThreadProcessEventHandler(HttpWebClient Sender, ThreadProcessEventArgs e); 293 294 public event ThreadProcessEventHandler ThreadProcessEnd; //发生多线程处理完毕事件 295 296 297 private int _FileLength; //下载文件的总大小 298 299 public int FileLength 300 { 301 get 302 { 303 return _FileLength; 304 } 305 } 306 307 /// <summary> 308 /// 分块下载文件 309 /// </summary> 310 /// <param name="Address">URL 地址</param> 311 /// <param name="FileName">保存到本地的路径文件名</param> 312 /// <param name="ChunksCount">块数,线程数</param> 313 public void DownloadFile(string Address, string FileName, int ChunksCount) 314 { 315 int p = 0; // position 316 int s = 0; // chunk size 317 string a = null; 318 HttpWebRequest hwrq; 319 HttpWebResponse hwrp = null; 320 try 321 { 322 hwrq = (HttpWebRequest)WebRequest.Create(this.GetUri(Address)); 323 hwrp = (HttpWebResponse)hwrq.GetResponse(); 324 long L = hwrp.ContentLength; 325 326 hwrq.Credentials = this.m_credentials; 327 328 L = ((L == -1) || (L > 0x7fffffff)) ? ((long)0x7fffffff) : L; //Int32.MaxValue 该常数的值为 2,147,483,647; 即十六进制的 0x7FFFFFFF 329 330 int l = (int)L; 331 332 this._FileLength = l; 333 334 // 在本地预定空间(竟然在多线程下不用先预定空间) 335 // FileStream sw = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); 336 // sw.Write(new byte[l], 0, l); 337 // sw.Close(); 338 // sw = null; 339 340 bool b = (hwrp.Headers["Accept-Ranges"] != null & hwrp.Headers["Accept-Ranges"] == "bytes"); 341 a = hwrp.Headers["Content-Disposition"]; //attachment 342 if (a != null) 343 { 344 a = a.Substring(a.LastIndexOf("filename=") + 9); 345 } 346 else 347 { 348 a = FileName; 349 } 350 351 int ss = s; 352 if (b) 353 { 354 s = l / ChunksCount; 355 if (s < 2 * 64 * 1024) //块大小至少为 128 K 字节 356 { 357 s = 2 * 64 * 1024; 358 } 359 ss = s; 360 int i = 0; 361 while (l > s) 362 { 363 l -= s; 364 if (l < s) 365 { 366 s += l; 367 } 368 if (i++ > 0) 369 { 370 DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, p, s, new ThreadCallbackHandler(this.DownloadFileChunk)); 371 // 单线程下载 372 // x.StartDownloadFileChunk(); 373 374 x.httpWebClient = this; 375 //多线程下载 376 Thread t = new Thread(new ThreadStart(x.StartDownloadFileChunk)); 377 //this.OnThreadProcess(t); 378 t.Start(); 379 } 380 p += s; 381 } 382 s = ss; 383 byte[] buffer = this.ResponseAsBytes(Address, hwrp, s, FileName); 384 this.OnThreadProcess(Thread.CurrentThread); 385 386 // lock (_SyncLockObject) 387 // { 388 // this._Bytes += buffer.Length; 389 // } 390 } 391 } 392 catch (Exception e) 393 { 394 ExceptionActions ea = ExceptionActions.Throw; 395 if (this.ExceptionOccurrs != null) 396 { 397 DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, p, s); 398 ExceptionEventArgs eea = new ExceptionEventArgs(e, x); 399 ExceptionOccurrs(this, eea); 400 ea = eea.ExceptionAction; 401 } 402 403 if (ea == ExceptionActions.Throw) 404 { 405 if (!(e is WebException) && !(e is SecurityException)) 406 { 407 throw new WebException("net_webclient", e); 408 } 409 throw; 410 } 411 } 412 413 } 414 415 internal void OnThreadProcess(Thread t) 416 { 417 if (ThreadProcessEnd != null) 418 { 419 ThreadProcessEventArgs tpea = new ThreadProcessEventArgs(t); 420 ThreadProcessEnd(this, tpea); 421 } 422 } 423 424 /// <summary> 425 /// 下载一个文件块,利用该方法可自行实现多线程断点续传 426 /// </summary> 427 /// <param name="Address">URL 地址</param> 428 /// <param name="FileName">保存到本地的路径文件名</param> 429 /// <param name="FromPosition">开始传的位置</param> 430 /// <param name="Length">块大小</param> 431 public void DownloadFileChunk(string Address, string FileName, int FromPosition, int Length) 432 { 433 HttpWebResponse hwrp = null; 434 string a = null; 435 try 436 { 437 //this._FileName = FileName; 438 HttpWebRequest hwrq = (HttpWebRequest)WebRequest.Create(this.GetUri(Address)); 439 //hwrq.Credentials = this.m_credentials; 440 hwrq.AddRange(FromPosition); 441 hwrp = (HttpWebResponse)hwrq.GetResponse(); 442 a = hwrp.Headers["Content-Disposition"]; //attachment 443 if (a != null) 444 { 445 a = a.Substring(a.LastIndexOf("filename=") + 9); 446 } 447 else 448 { 449 a = FileName; 450 } 451 452 byte[] buffer = this.ResponseAsBytes(Address, hwrp, Length, FileName); 453 // lock (_SyncLockObject) 454 // { 455 // this._Bytes += buffer.Length; 456 // } 457 } 458 catch (Exception e) 459 { 460 ExceptionActions ea = ExceptionActions.Throw; 461 if (this.ExceptionOccurrs != null) 462 { 463 DownLoadState x = new DownLoadState(Address, hwrp.ResponseUri.AbsolutePath, FileName, a, FromPosition, Length); 464 ExceptionEventArgs eea = new ExceptionEventArgs(e, x); 465 ExceptionOccurrs(this, eea); 466 ea = eea.ExceptionAction; 467 } 468 469 if (ea == ExceptionActions.Throw) 470 { 471 if (!(e is WebException) && !(e is SecurityException)) 472 { 473 throw new WebException("net_webclient", e); 474 } 475 throw; 476 } 477 } 478 } 479 480 internal byte[] ResponseAsBytes(string RequestURL, WebResponse Response, long Length, string FileName) 481 { 482 string a = null; //AttachmentName 483 int P = 0; //整个文件的位置指针 484 int num2 = 0; 485 try 486 { 487 a = Response.Headers["Content-Disposition"]; //attachment 488 if (a != null) 489 { 490 a = a.Substring(a.LastIndexOf("filename=") + 9); 491 } 492 493 long num1 = Length; //Response.ContentLength; 494 bool flag1 = false; 495 if (num1 == -1) 496 { 497 flag1 = true; 498 num1 = 0x10000; //64k 499 } 500 byte[] buffer1 = new byte[(int)num1]; 501 502 503 int p = 0; //本块的位置指针 504 505 string s = Response.Headers["Content-Range"]; 506 if (s != null) 507 { 508 s = s.Replace("bytes ", ""); 509 s = s.Substring(0, s.IndexOf("-")); 510 P = Convert.ToInt32(s); 511 } 512 int num3 = 0; 513 514 Stream S = Response.GetResponseStream(); 515 do 516 { 517 num2 = S.Read(buffer1, num3, ((int)num1) - num3); 518 519 num3 += num2; 520 if (flag1 && (num3 == num1)) 521 { 522 num1 += 0x10000; 523 byte[] buffer2 = new byte[(int)num1]; 524 Buffer.BlockCopy(buffer1, 0, buffer2, 0, num3); 525 buffer1 = buffer2; 526 } 527 528 // lock (_SyncLockObject) 529 // { 530 // this._bytes += num2; 531 // } 532 if (num2 > 0) 533 { 534 if (this.DataReceive != null) 535 { 536 byte[] buffer = new byte[num2]; 537 Buffer.BlockCopy(buffer1, p, buffer, 0, buffer.Length); 538 DownLoadState dls = new DownLoadState(RequestURL, Response.ResponseUri.AbsolutePath, FileName, a, P, num2, buffer); 539 DownLoadEventArgs dlea = new DownLoadEventArgs(dls); 540 //触发事件 541 this.OnDataReceive(dlea); 542 //System.Threading.Thread.Sleep(100); 543 } 544 p += num2; //本块的位置指针 545 P += num2; //整个文件的位置指针 546 } 547 else 548 { 549 break; 550 } 551 552 } 553 while (num2 != 0); 554 555 S.Close(); 556 S = null; 557 if (flag1) 558 { 559 byte[] buffer3 = new byte[num3]; 560 Buffer.BlockCopy(buffer1, 0, buffer3, 0, num3); 561 buffer1 = buffer3; 562 } 563 return buffer1; 564 } 565 catch (Exception e) 566 { 567 ExceptionActions ea = ExceptionActions.Throw; 568 if (this.ExceptionOccurrs != null) 569 { 570 DownLoadState x = new DownLoadState(RequestURL, Response.ResponseUri.AbsolutePath, FileName, a, P, num2); 571 ExceptionEventArgs eea = new ExceptionEventArgs(e, x); 572 ExceptionOccurrs(this, eea); 573 ea = eea.ExceptionAction; 574 } 575 576 if (ea == ExceptionActions.Throw) 577 { 578 if (!(e is WebException) && !(e is SecurityException)) 579 { 580 throw new WebException("net_webclient", e); 581 } 582 throw; 583 } 584 return null; 585 } 586 } 587 588 private void OnDataReceive(DownLoadEventArgs e) 589 { 590 //触发数据到达事件 591 DataReceive(this, e); 592 } 593 594 public byte[] UploadFile(string address, string fileName) 595 { 596 return this.UploadFile(address, "POST", fileName, "file"); 597 } 598 599 public string UploadFileEx(string address, string method, string fileName, string fieldName) 600 { 601 return Encoding.ASCII.GetString(UploadFile(address, method, fileName, fieldName)); 602 } 603 604 public byte[] UploadFile(string address, string method, string fileName, string fieldName) 605 { 606 byte[] buffer4; 607 FileStream stream1 = null; 608 try 609 { 610 fileName = Path.GetFullPath(fileName); 611 string text1 = "---------------------" + DateTime.Now.Ticks.ToString("x"); 612 613 string text2 = "application/octet-stream"; 614 615 stream1 = new FileStream(fileName, FileMode.Open, FileAccess.Read); 616 WebRequest request1 = WebRequest.Create(this.GetUri(address)); 617 request1.Credentials = this.m_credentials; 618 request1.ContentType = "multipart/form-data; boundary=" + text1; 619 620 request1.Method = method; 621 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" }; 622 string text3 = string.Concat(textArray1); 623 byte[] buffer1 = Encoding.UTF8.GetBytes(text3); 624 byte[] buffer2 = Encoding.ASCII.GetBytes("\r\n--" + text1 + "\r\n"); 625 long num1 = 0x7fffffffffffffff; 626 try 627 { 628 num1 = stream1.Length; 629 request1.ContentLength = (num1 + buffer1.Length) + buffer2.Length; 630 } 631 catch 632 { 633 } 634 byte[] buffer3 = new byte[Math.Min(0x2000, (int)num1)]; 635 using (Stream stream2 = request1.GetRequestStream()) 636 { 637 int num2; 638 stream2.Write(buffer1, 0, buffer1.Length); 639 do 640 { 641 num2 = stream1.Read(buffer3, 0, buffer3.Length); 642 if (num2 != 0) 643 { 644 stream2.Write(buffer3, 0, num2); 645 } 646 } 647 while (num2 != 0); 648 stream2.Write(buffer2, 0, buffer2.Length); 649 } 650 stream1.Close(); 651 stream1 = null; 652 WebResponse response1 = request1.GetResponse(); 653 654 buffer4 = this.ResponseAsBytes(response1); 655 } 656 catch (Exception exception1) 657 { 658 if (stream1 != null) 659 { 660 stream1.Close(); 661 stream1 = null; 662 } 663 if (!(exception1 is WebException) && !(exception1 is SecurityException)) 664 { 665 //throw new WebException(SR.GetString("net_webclient"), exception1); 666 throw new WebException("net_webclient", exception1); 667 } 668 throw; 669 } 670 return buffer4; 671 } 672 673 private byte[] ResponseAsBytes(WebResponse response) 674 { 675 int num2; 676 long num1 = response.ContentLength; 677 bool flag1 = false; 678 if (num1 == -1) 679 { 680 flag1 = true; 681 num1 = 0x10000; 682 } 683 byte[] buffer1 = new byte[(int)num1]; 684 Stream stream1 = response.GetResponseStream(); 685 int num3 = 0; 686 do 687 { 688 num2 = stream1.Read(buffer1, num3, ((int)num1) - num3); 689 num3 += num2; 690 if (flag1 && (num3 == num1)) 691 { 692 num1 += 0x10000; 693 byte[] buffer2 = new byte[(int)num1]; 694 Buffer.BlockCopy(buffer1, 0, buffer2, 0, num3); 695 buffer1 = buffer2; 696 } 697 } 698 while (num2 != 0); 699 stream1.Close(); 700 if (flag1) 701 { 702 byte[] buffer3 = new byte[num3]; 703 Buffer.BlockCopy(buffer1, 0, buffer3, 0, num3); 704 buffer1 = buffer3; 705 } 706 return buffer1; 707 } 708 709 private NameValueCollection m_requestParameters; 710 private Uri m_baseAddress; 711 private ICredentials m_credentials = CredentialCache.DefaultCredentials; 712 713 public ICredentials Credentials 714 { 715 get 716 { 717 return this.m_credentials; 718 } 719 set 720 { 721 this.m_credentials = value; 722 } 723 } 724 725 public NameValueCollection QueryString 726 { 727 get 728 { 729 if (this.m_requestParameters == null) 730 { 731 this.m_requestParameters = new NameValueCollection(); 732 } 733 return this.m_requestParameters; 734 } 735 set 736 { 737 this.m_requestParameters = value; 738 } 739 } 740 741 public string BaseAddress 742 { 743 get 744 { 745 if (this.m_baseAddress != null) 746 { 747 return this.m_baseAddress.ToString(); 748 } 749 return string.Empty; 750 } 751 set 752 { 753 if ((value == null) || (value.Length == 0)) 754 { 755 this.m_baseAddress = null; 756 } 757 else 758 { 759 try 760 { 761 this.m_baseAddress = new Uri(value); 762 } 763 catch (Exception exception1) 764 { 765 throw new ArgumentException("value", exception1); 766 } 767 } 768 } 769 } 770 771 private Uri GetUri(string path) 772 { 773 Uri uri1; 774 try 775 { 776 if (this.m_baseAddress != null) 777 { 778 uri1 = new Uri(this.m_baseAddress, path); 779 } 780 else 781 { 782 uri1 = new Uri(path); 783 } 784 if (this.m_requestParameters == null) 785 { 786 return uri1; 787 } 788 StringBuilder builder1 = new StringBuilder(); 789 string text1 = string.Empty; 790 for (int num1 = 0; num1 < this.m_requestParameters.Count; num1++) 791 { 792 builder1.Append(text1 + this.m_requestParameters.AllKeys[num1] + "=" + this.m_requestParameters[num1]); 793 text1 = "&"; 794 } 795 UriBuilder builder2 = new UriBuilder(uri1); 796 builder2.Query = builder1.ToString(); 797 uri1 = builder2.Uri; 798 } 799 catch (UriFormatException) 800 { 801 uri1 = new Uri(Path.GetFullPath(path)); 802 } 803 return uri1; 804 } 805 806 } 807 808 /// <summary> 809 /// 测试类 810 /// </summary> 811 class AppTest 812 { 813 int _k = 0; 814 int _K = 0; 815 816 static void Mainyyy() 817 { 818 AppTest a = new AppTest(); 819 HttpWebClient x = new HttpWebClient(); 820 821 a._K = 10; 822 823 //订阅 DataReceive 事件 824 x.DataReceive += new HttpWebClient.DataReceiveEventHandler(a.x_DataReceive); 825 //订阅 ExceptionOccurrs 事件 826 x.ExceptionOccurrs += new HttpWebClient.ExceptionEventHandler(a.x_ExceptionOccurrs); 827 828 x.ThreadProcessEnd += new HttpWebClient.ThreadProcessEventHandler(a.x_ThreadProcessEnd); 829 string F = "E:\\"; //http://172.30.0.98/Files/eclipse-SDK-3.6.1-win32.zip 830 a._F = F; 831 832 string f = F.Substring(F.LastIndexOf("/") + 1); 833 834 //x.DownloadFile(F, @"F:\temp\" + f, a._K); 835 //int beginIndex = 250000; 836 //int SIZE = 250000; 837 //x.DownloadFileChunk(F, @"F:\temp\" + f, beginIndex, SIZE); 838 839 string uploadfile = "F:\\temp\\eclipse-SDK-3.6.1-win32.zip"; 840 string str = x.UploadFileEx(F, "POST", uploadfile, f); 841 System.Console.WriteLine(str); 842 Console.ReadKey(); 843 } 844 845 string bs = ""; //用于记录上次的位数 846 bool b = false; 847 private int i = 0; 848 private static object _SyncLockObject = new object(); 849 string _F; 850 string _f; 851 852 private void x_DataReceive(HttpWebClient Sender, DownLoadEventArgs e) 853 { 854 if (!this.b) 855 { 856 lock (_SyncLockObject) 857 { 858 if (!this.b) 859 { 860 System.Console.Write(System.DateTime.Now.ToString() + " 已接收数据: "); 861 this.b = true; 862 } 863 } 864 } 865 string f = e.DownloadState.FileName; 866 if (e.DownloadState.AttachmentName != null) 867 f = System.IO.Path.GetDirectoryName(f) + @"\" + e.DownloadState.AttachmentName; 868 869 this._f = f; 870 871 using (System.IO.FileStream sw = new System.IO.FileStream(f, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)) 872 { 873 sw.Position = e.DownloadState.Position; 874 sw.Write(e.DownloadState.Data, 0, e.DownloadState.Data.Length); 875 sw.Close(); 876 } 877 string s = System.DateTime.Now.ToString(); 878 lock (_SyncLockObject) 879 { 880 this.i += e.DownloadState.Data.Length; 881 System.Console.Write(bs + "\b\b\b\b\b\b\b\b\b\b" + i + " / " + Sender.FileLength + " 字节数据 " + s); 882 this.bs = new string('\b', Digits(i) + 3 + Digits(Sender.FileLength) + s.Length); 883 } 884 } 885 886 int Digits(int n) //数字所占位数 887 { 888 n = System.Math.Abs(n); 889 n = n / 10; 890 int i = 1; 891 while (n > 0) 892 { 893 n = n / 10; 894 i++; 895 } 896 return i; 897 } 898 899 private void x_ExceptionOccurrs(HttpWebClient Sender, ExceptionEventArgs e) 900 { 901 System.Console.WriteLine(e.Exception.Message); 902 //发生异常重新下载相当于断点续传,你可以自己自行选择处理方式 903 HttpWebClient x = new HttpWebClient(); 904 x.DownloadFileChunk(this._F, this._f, e.DownloadState.Position, e.DownloadState.Length); 905 e.ExceptionAction = ExceptionActions.Ignore; 906 } 907 908 private void x_ThreadProcessEnd(HttpWebClient Sender, ThreadProcessEventArgs e) 909 { 910 //if (e.thread.ThreadState == System.Threading.ThreadState.Stopped) 911 if (this._k++ == this._K - 1) 912 System.Console.WriteLine("\nend"); 913 } 914 } 915 }
工欲善其事,必先利其器。