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 }