借助WebService实现多线程上传文件

WebService的帮助下,进行多线程上传文件是非常简单。因此我只做个简单的例子,那么如果想要实现此功能的朋友,可以在我的基础上进行扩展。 

首先说说服务器端,只需要提供一个能允许多线程写文件的函数即可,具体代码如下。

 1 [WebMethod]
 2 
 3 public bool UploadFileData( string FileName, int StartPosition, byte[] bData )
 4 
 5 {
 6 
 7     string strFullName = Server.MapPath( "Uploads" ) + @""" + FileName;
 8 
 9     FileStream fs = null;
10 
11     try
12 
13     {
14 
15         fs = new FileStream( strFullName, FileMode.OpenOrCreate,
16 
17             FileAccess.Write, FileShare.Write );
18 
19     }
20 
21     catch( IOException err )
22 
23     {
24 
25         Session["ErrorMessage"] = err.Message;
26 
27         return false;
28 
29     }
30 
31     using( fs )
32 
33     {
34 
35         fs.Position = StartPosition;
36 
37         fs.Write( bData, 0, bData.Length );
38 
39     }
40 
41     return true;
42 
43 }
View Code

  其中“Uploads”是在服务程序所在目录下的一个子目录,需要设置ASPNET用户对此目录具有可写权限。

相对于服务器端来说,客户端要稍微复杂一些,因为要牵扯到多线程的问题。为了更好的传递参数,我用一个线程类来完成。具体如下。

  1     public delegate void UploadFileData( string FileName, int StartPos, byte[] bData );
  2 
  3     ///<summary>
  4 
  5     /// FileThread: a class for sub-thread
  6 
  7     ///</summary>
  8 
  9     sealed class FileThread
 10 
 11     {
 12 
 13         private int nStartPos;
 14 
 15         private int nTotalBytes;
 16 
 17         private string strFileName;
 18 
 19         public static UploadFileData UploadHandle;
 20 
 21         ///<summary>
 22 
 23         /// Constructor
 24 
 25         ///</summary>
 26 
 27         ///<param name="StartPos"></param>
 28 
 29         ///<param name="TotalBytes"></param>
 30 
 31         ///<param name="FileName"></param>
 32 
 33         public FileThread( int StartPos, int TotalBytes, string FileName )
 34 
 35         {
 36 
 37             //Init thread variant
 38 
 39             nStartPos = StartPos;
 40 
 41             nTotalBytes = TotalBytes;
 42 
 43             strFileName = FileName;
 44 
 45             //Only for debug
 46 
 47             Debug.WriteLine( string.Format( "File name:{0} position: {1} total byte:{2}",
 48 
 49                 strFileName, nStartPos, nTotalBytes ) );
 50 
 51         }
 52 
 53         ///<summary>
 54 
 55         /// Sub-thread entry function
 56 
 57         ///</summary>
 58 
 59         ///<param name="stateinfo"></param>
 60 
 61         public void UploadFile( object stateinfo )
 62 
 63         {
 64 
 65             int nRealRead, nBufferSize;
 66 
 67             const int BUFFER_SIZE = 10240;
 68 
 69             using( FileStream fs = new FileStream( strFileName,
 70 
 71                        FileMode.Open, FileAccess.Read,
 72 
 73                        FileShare.Read ) )
 74 
 75             {
 76 
 77                 string sName = strFileName.Substring( strFileName.LastIndexOf( """" ) + 1 );
 78 
 79                 byte[] bBuffer = new byte[BUFFER_SIZE];//Init 10k buffer
 80 
 81                 fs.Position = nStartPos;
 82 
 83                 nRealRead = 0;
 84 
 85                 do
 86 
 87                 {
 88 
 89                     nBufferSize = BUFFER_SIZE;
 90 
 91                     if( nRealRead + BUFFER_SIZE > nTotalBytes )
 92 
 93                         nBufferSize = nTotalBytes - nRealRead;
 94 
 95                     nBufferSize = fs.Read( bBuffer, 0, nBufferSize );
 96 
 97                     if( nBufferSize == BUFFER_SIZE )
 98 
 99                         UploadHandle( sName,
100 
101                             nRealRead + nStartPos,
102 
103                             bBuffer );
104 
105                     else if( nBufferSize > 0 )
106 
107                     {
108 
109                         //Copy data
110 
111                         byte[] bytData = new byte[nBufferSize];
112 
113                         Array.Copy( bBuffer,0, bytData, 0, nBufferSize );
114 
115                         UploadHandle( sName,
116 
117                             nRealRead + nStartPos,
118 
119                             bytData );
120 
121                     }
122 
123                     nRealRead += nBufferSize;
124 
125                 }
126 
127                 while( nRealRead < nTotalBytes );
128 
129             }
130 
131             //Release signal
132 
133             ManualResetEvent mr = stateinfo as ManualResetEvent;
134 
135             if( mr != null )
136 
137                 mr.Set();
138 
139         }
140 
141     }
142 
143  
144 
145 那么在执行的时候,要创建线程类对象,并为每一个每个线程设置一个信号量,从而能在所有线程都结束的时候得到通知,大致的代码如下。
146 
147     FileInfo fi = new FileInfo( txtFileName.Text );
148 
149     if( fi.Exists )
150 
151     {
152 
153         btnUpload.Enabled = false;//Avoid upload twice
154 
155         //Init signals
156 
157         ManualResetEvent[] events = new ManualResetEvent[5];
158 
159         //Devide blocks
160 
161         int nTotalBytes = (int)( fi.Length / 5 );
162 
163         for( int i = 0; i < 5; i++ )
164 
165         {
166 
167             events[i] = new ManualResetEvent( false );
168 
169             FileThread thdSub = new FileThread(
170 
171                 i * nTotalBytes,
172 
173                 ( fi.Length - i * nTotalBytes ) > nTotalBytes ? nTotalBytes:(int)( fi.Length - i * nTotalBytes ),
174 
175                 fi.FullName );
176 
177             ThreadPool.QueueUserWorkItem( new WaitCallback( thdSub.UploadFile ), events[i] );
178 
179         }
180 
181         //Wait for threads finished
182 
183         WaitHandle.WaitAll( events );
184 
185         //Reset button status
186 
187         btnUpload.Enabled = true;
188 
189     }
View Code

总体来说,程序还是相对比较简单,而我也只是做了个简单例子而已,一些细节都没有进行处理

本来想打包提供给大家下载,没想到CSDNBlog对于这点做的太差,老是异常。

如下是客户端的完整代码。 

  1 //--------------------------- Multi-thread Upload Demo ---------------------------------------
  2 
  3  
  4 
  5 //--------------------------------------------------------------------------------------------
  6 
  7  
  8 
  9 //---File:          frmUpload
 10 
 11  
 12 
 13 //---Description:   The multi-thread upload form file to demenstrate howto use multi-thread to
 14 
 15  
 16 
 17 //                  upload files
 18 
 19  
 20 
 21 //---Author:        Knight
 22 
 23  
 24 
 25 //---Date:          Oct.12, 2006
 26 
 27  
 28 
 29 //--------------------------------------------------------------------------------------------
 30 
 31  
 32 
 33 //---------------------------{Multi-thread Upload Demo}---------------------------------------
 34 
 35  
 36 
 37 using System;
 38 
 39  
 40 
 41 using System.Drawing;
 42 
 43  
 44 
 45 using System.Collections;
 46 
 47  
 48 
 49 using System.ComponentModel;
 50 
 51  
 52 
 53 using System.Windows.Forms;
 54 
 55  
 56 
 57 using System.Data;
 58 
 59  
 60 
 61 namespace CSUpload
 62 
 63  
 64 
 65 {
 66 
 67  
 68 
 69     using System.IO;
 70 
 71  
 72 
 73     using System.Diagnostics;
 74 
 75  
 76 
 77     using System.Threading;
 78 
 79  
 80 
 81     using WSUploadFile;//Web-service reference namespace
 82 
 83  
 84 
 85     ///<summary>
 86 
 87  
 88 
 89     /// Summary description for Form1.
 90 
 91  
 92 
 93     ///</summary>
 94 
 95  
 96 
 97     public class frmUpload : System.Windows.Forms.Form
 98 
 99  
100 
101     {
102 
103  
104 
105         private System.Windows.Forms.TextBox txtFileName;
106 
107  
108 
109         private System.Windows.Forms.Button btnBrowse;
110 
111  
112 
113         private System.Windows.Forms.Button btnUpload;
114 
115  
116 
117         ///<summary>
118 
119  
120 
121         /// Required designer variable.
122 
123  
124 
125         ///</summary>
126 
127  
128 
129         private System.ComponentModel.Container components = null;
130 
131  
132 
133         public frmUpload()
134 
135  
136 
137         {
138 
139  
140 
141             //
142 
143  
144 
145             // Required for Windows Form Designer support
146 
147  
148 
149             //
150 
151  
152 
153             InitializeComponent();
154 
155  
156 
157             //
158 
159  
160 
161             // TODO: Add any constructor code after InitializeComponent call
162 
163  
164 
165             //
166 
167  
168 
169         }
170 
171  
172 
173         ///<summary>
174 
175  
176 
177         /// Clean up any resources being used.
178 
179  
180 
181         ///</summary>
182 
183  
184 
185         protected override void Dispose( bool disposing )
186 
187  
188 
189         {
190 
191  
192 
193             if( disposing )
194 
195  
196 
197             {
198 
199  
200 
201                 if (components != null)
202 
203  
204 
205                 {
206 
207  
208 
209                     components.Dispose();
210 
211  
212 
213                 }
214 
215  
216 
217             }
218 
219  
220 
221             base.Dispose( disposing );
222 
223  
224 
225         }
226 
227  
228 
229         #region Windows Form Designer generated code
230 
231  
232 
233         ///<summary>
234 
235  
236 
237         /// Required method for Designer support - do not modify
238 
239  
240 
241         /// the contents of this method with the code editor.
242 
243  
244 
245         ///</summary>
246 
247  
248 
249         private void InitializeComponent()
250 
251  
252 
253         {
254 
255  
256 
257             this.txtFileName = new System.Windows.Forms.TextBox();
258 
259  
260 
261             this.btnBrowse = new System.Windows.Forms.Button();
262 
263  
264 
265             this.btnUpload = new System.Windows.Forms.Button();
266 
267  
268 
269             this.SuspendLayout();
270 
271  
272 
273             //
274 
275  
276 
277             // txtFileName
278 
279  
280 
281             //
282 
283  
284 
285             this.txtFileName.Location = new System.Drawing.Point(16, 24);
286 
287  
288 
289             this.txtFileName.Name = "txtFileName";
290 
291  
292 
293             this.txtFileName.Size = new System.Drawing.Size(248, 20);
294 
295  
296 
297             this.txtFileName.TabIndex = 0;
298 
299  
300 
301             this.txtFileName.Text = "";
302 
303  
304 
305             //
306 
307  
308 
309             // btnBrowse
310 
311  
312 
313             //
314 
315  
316 
317             this.btnBrowse.Location = new System.Drawing.Point(272, 24);
318 
319  
320 
321             this.btnBrowse.Name = "btnBrowse";
322 
323  
324 
325             this.btnBrowse.TabIndex = 1;
326 
327  
328 
329             this.btnBrowse.Text = "&Browse...";
330 
331  
332 
333             this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click);
334 
335  
336 
337             //
338 
339  
340 
341             // btnUpload
342 
343  
344 
345             //
346 
347  
348 
349             this.btnUpload.Location = new System.Drawing.Point(272, 56);
350 
351  
352 
353             this.btnUpload.Name = "btnUpload";
354 
355  
356 
357             this.btnUpload.TabIndex = 2;
358 
359  
360 
361             this.btnUpload.Text = "&Upload";
362 
363  
364 
365             this.btnUpload.Click += new System.EventHandler(this.btnUpload_Click);
366 
367  
368 
369             //
370 
371  
372 
373             // frmUpload
374 
375  
376 
377             //
378 
379  
380 
381             this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
382 
383  
384 
385             this.ClientSize = new System.Drawing.Size(370, 111);
386 
387  
388 
389             this.Controls.Add(this.btnUpload);
390 
391  
392 
393             this.Controls.Add(this.btnBrowse);
394 
395  
396 
397             this.Controls.Add(this.txtFileName);
398 
399  
400 
401             this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
402 
403  
404 
405             this.MaximizeBox = false;
406 
407  
408 
409             this.Name = "frmUpload";
410 
411  
412 
413             this.Text = "Upload";
414 
415  
416 
417             this.Load += new System.EventHandler(this.frmUpload_Load);
418 
419  
420 
421             this.ResumeLayout(false);
422 
423  
424 
425         }
426 
427  
428 
429         #endregion
430 
431  
432 
433         ///<summary>
434 
435  
436 
437         /// The main entry point for the application.
438 
439  
440 
441         ///</summary>
442 
443  
444 
445         static void Main()
446 
447  
448 
449         {
450 
451  
452 
453             Application.Run(new frmUpload());
454 
455  
456 
457         }
458 
459  
460 
461         private FileUpload myUpload = new FileUpload();
462 
463  
464 
465         private void UploadData( string FileName, int StartPos, byte[] bData )
466 
467  
468 
469         {
470 
471  
472 
473             //Call web service upload
474 
475  
476 
477             myUpload.UploadFileData( FileName, StartPos, bData );
478 
479  
480 
481         }
482 
483  
484 
485         private void btnUpload_Click(object sender, System.EventArgs e)
486 
487  
488 
489         {
490 
491  
492 
493             FileInfo fi = new FileInfo( txtFileName.Text );
494 
495  
496 
497             if( fi.Exists )
498 
499  
500 
501             {
502 
503  
504 
505                 btnUpload.Enabled = false;//Avoid upload twice
506 
507  
508 
509                 //Init signals
510 
511  
512 
513                 ManualResetEvent[] events = new ManualResetEvent[5];
514 
515  
516 
517                 //Devide blocks
518 
519  
520 
521                 int nTotalBytes = (int)( fi.Length / 5 );
522 
523  
524 
525                 for( int i = 0; i < 5; i++ )
526 
527  
528 
529                 {
530 
531  
532 
533                     events[i] = new ManualResetEvent( false );
534 
535  
536 
537                     FileThread thdSub = new FileThread(
538 
539  
540 
541                         i * nTotalBytes,
542 
543  
544 
545                         ( fi.Length - i * nTotalBytes ) > nTotalBytes ? nTotalBytes:(int)( fi.Length - i * nTotalBytes ),
546 
547  
548 
549                         fi.FullName );
550 
551  
552 
553                     ThreadPool.QueueUserWorkItem( new WaitCallback( thdSub.UploadFile ), events[i] );
554 
555  
556 
557                 }
558 
559  
560 
561                 //Wait for threads finished
562 
563  
564 
565                 WaitHandle.WaitAll( events );
566 
567  
568 
569                 //Reset button status
570 
571  
572 
573                 btnUpload.Enabled = true;
574 
575  
576 
577             }
578 
579  
580 
581        
582 
583  
584 
585         }
586 
587  
588 
589         private void frmUpload_Load(object sender, System.EventArgs e)
590 
591  
592 
593         {
594 
595  
596 
597             FileThread.UploadHandle = new UploadFileData( this.UploadData );
598 
599  
600 
601         }
602 
603  
604 
605         private void btnBrowse_Click(object sender, System.EventArgs e)
606 
607  
608 
609         {
610 
611  
612 
613             if( fileOpen.ShowDialog() == DialogResult.OK )
614 
615  
616 
617                 txtFileName.Text = fileOpen.FileName;
618 
619  
620 
621         }
622 
623  
624 
625         private OpenFileDialog fileOpen = new OpenFileDialog();
626 
627  
628 
629        
630 
631  
632 
633     }
634 
635  
636 
637     public delegate void UploadFileData( string FileName, int StartPos, byte[] bData );
638 
639  
640 
641     ///<summary>
642 
643  
644 
645     /// FileThread: a class for sub-thread
646 
647  
648 
649     ///</summary>
650 
651  
652 
653     sealed class FileThread
654 
655  
656 
657     {
658 
659  
660 
661         private int nStartPos;
662 
663  
664 
665         private int nTotalBytes;
666 
667  
668 
669         private string strFileName;
670 
671  
672 
673         public static UploadFileData UploadHandle;
674 
675  
676 
677         ///<summary>
678 
679  
680 
681         /// Constructor
682 
683  
684 
685         ///</summary>
686 
687  
688 
689         ///<param name="StartPos"></param>
690 
691  
692 
693         ///<param name="TotalBytes"></param>
694 
695  
696 
697         ///<param name="FileName"></param>
698 
699  
700 
701         public FileThread( int StartPos, int TotalBytes, string FileName )
702 
703  
704 
705         {
706 
707  
708 
709             //Init thread variant
710 
711  
712 
713             nStartPos = StartPos;
714 
715  
716 
717             nTotalBytes = TotalBytes;
718 
719  
720 
721             strFileName = FileName;
722 
723  
724 
725             //Only for debug
726 
727  
728 
729             Debug.WriteLine( string.Format( "File name:{0} position: {1} total byte:{2}",
730 
731  
732 
733                 strFileName, nStartPos, nTotalBytes ) );
734 
735  
736 
737         }
738 
739  
740 
741         ///<summary>
742 
743  
744 
745         /// Sub-thread entry function
746 
747  
748 
749         ///</summary>
750 
751  
752 
753         ///<param name="stateinfo"></param>
754 
755  
756 
757         public void UploadFile( object stateinfo )
758 
759  
760 
761         {
762 
763  
764 
765             int nRealRead, nBufferSize;
766 
767  
768 
769             const int BUFFER_SIZE = 10240;
770 
771  
772 
773             using( FileStream fs = new FileStream( strFileName,
774 
775  
776 
777                        FileMode.Open, FileAccess.Read,
778 
779  
780 
781                        FileShare.Read ) )
782 
783  
784 
785             {
786 
787  
788 
789                 string sName = strFileName.Substring( strFileName.LastIndexOf( """" ) + 1 );
790 
791  
792 
793                 byte[] bBuffer = new byte[BUFFER_SIZE];//Init 10k buffer
794 
795  
796 
797                 fs.Position = nStartPos;
798 
799  
800 
801                 nRealRead = 0;
802 
803  
804 
805                 do
806 
807  
808 
809                 {
810 
811  
812 
813                     nBufferSize = BUFFER_SIZE;
814 
815  
816 
817                     if( nRealRead + BUFFER_SIZE > nTotalBytes )
818 
819  
820 
821                         nBufferSize = nTotalBytes - nRealRead;
822 
823  
824 
825                     nBufferSize = fs.Read( bBuffer, 0, nBufferSize );
826 
827  
828 
829                     if( nBufferSize == BUFFER_SIZE )
830 
831  
832 
833                         UploadHandle( sName,
834 
835  
836 
837                             nRealRead + nStartPos,
838 
839  
840 
841                             bBuffer );
842 
843  
844 
845                     else if( nBufferSize > 0 )
846 
847  
848 
849                     {
850 
851  
852 
853                         //Copy data
854 
855  
856 
857                         byte[] bytData = new byte[nBufferSize];
858 
859  
860 
861                         Array.Copy( bBuffer,0, bytData, 0, nBufferSize );
862 
863  
864 
865                         UploadHandle( sName,
866 
867  
868 
869                             nRealRead + nStartPos,
870 
871  
872 
873                             bytData );
874 
875  
876 
877                     }
878                     nRealRead += nBufferSize;
879                 }
880                 while( nRealRead < nTotalBytes );
881             }
882 
883             //Release signal
884 
885             ManualResetEvent mr = stateinfo as ManualResetEvent;
886 
887             if( mr != null )
888 
889                 mr.Set();
890         }
891 
892     }
893  
894 }
View Code

 

posted on 2014-01-15 13:34  JimSow  阅读(399)  评论(0编辑  收藏  举报

导航