【转】Asp.net 2.0 文件下载[支持多线程, 断点续传功能](示例代码下载)
(一) . 概述
最近做了个C/S文件下载工具, 支持多任务, 多线程和断点续传功能. 其中部分代码是从网上找来的, 自己改了
许多Bug, 并增加断点续传等功能.
由于公司具有代码所有权, 不能将源代码共享. 自己对比较Asp.net感兴趣, 业余时间自己做了个简单的, 基于Asp.net 2.0的, 功能虽然不是很强大, 但已经实现了多线程, 断点续传功能. 分享一下, 互相学习! 互相借鉴!
(二).运行效果
(三). 代码
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 /// 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 >
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
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 ///
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
posted on
2007-06-22 11:16 ms_dos 阅读(
...) 评论(
...) 编辑 收藏