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 }
工欲善其事,必先利其器。
原文地址:https://www.cnblogs.com/zhangzhu/p/2836159.html