利用C#编写WebService进行多线程上传

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

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

 

[WebMethod]
public   bool  UploadFileData(  string  FileName,  int  StartPosition,  byte [] bData )
{
 
string strFullName = Server.MapPath( "Uploads" ) + @"" + FileName;
 FileStream fs 
= null;
 
try
 
{
  fs 
= new FileStream( strFullName, FileMode.OpenOrCreate, 
   FileAccess.Write, FileShare.Write );
 }

 
catch( IOException err )
 
{
  Session[
"ErrorMessage"= err.Message;
  
return false;
 }


 
using( fs )
 
{
  fs.Position 
= StartPosition;
  fs.Write( bData, 
0, bData.Length );
 }

 
return true;
}


  

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

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

 

public   delegate   void  UploadFileData(  string  FileName,  int  StartPos,  byte [] bData );

 
/// 
 
/// FileThread: a class for sub-thread
 
/// 

  sealed   class  FileThread
 
{
  
private int nStartPos;
  
private int nTotalBytes;
  
private string strFileName;
  
public static UploadFileData UploadHandle;

  
/// 
  
/// Constructor
  
/// 

  //


  
/// 
  
/// 

  public FileThread( int StartPos, int TotalBytes, string FileName )
  
{
   
//Init thread variant
   nStartPos = StartPos;
   nTotalBytes 
= TotalBytes;
   strFileName 
= FileName; 

   
//Only for debug
   Debug.WriteLine( string.Format( "File name:{0} position: {1} total byte:{2}",
   strFileName, nStartPos, nTotalBytes ) );
  }


  
/// 
  
/// Sub-thread entry function 
  
/// 
  
/// 

  public void UploadFile( object stateinfo )
  
{
   
int nRealRead, nBufferSize;
   
const int BUFFER_SIZE = 10240;

   
using( FileStream fs = new FileStream( strFileName,
        FileMode.Open, FileAccess.Read,
        FileShare.Read ) )
   
{
    
string sName = strFileName.Substring( strFileName.LastIndexOf( "/" ) + 1 );
    
byte[] bBuffer = new byte[BUFFER_SIZE];//Init 10k buffer
    fs.Position = nStartPos;
    nRealRead 
= 0;

    
do
    
{
     nBufferSize 
= BUFFER_SIZE;
     
if( nRealRead + BUFFER_SIZE > nTotalBytes )
     nBufferSize 
= nTotalBytes - nRealRead;
     nBufferSize 
= fs.Read( bBuffer, 0, nBufferSize );
     
if( nBufferSize == BUFFER_SIZE )
      UploadHandle( sName,
      nRealRead 
+ nStartPos,
       bBuffer );
     
else if( nBufferSize > 0 )
     
{
      
//Copy data 
      byte[] bytData = new byte[nBufferSize];
      Array.Copy( bBuffer,
0, bytData, 0, nBufferSize );
      UploadHandle( sName, nRealRead 
+ nStartPos, bytData );
     }


     nRealRead 
+= nBufferSize;
    }

    
while( nRealRead < nTotalBytes );
   }
 


   
//Release signal
   ManualResetEvent mr = stateinfo as ManualResetEvent;
   
if( mr != null )
    mr.Set();
  }

 }


 

   那么在执行的时候,要创建线程类对象,并为每一个每个线程设置一个信号量,从而能在所有线程都结束的时候得到通知,大致的代码如下。
 

FileInfo fi  =   new  FileInfo( txtFileName.Text );
 
if ( fi.Exists )
 
{
  btnUpload.Enabled 
= false;//Avoid upload twice

  
//Init signals
  ManualResetEvent[] events = new ManualResetEvent[5];

  
//Devide blocks
  int nTotalBytes = (int)( fi.Length / 5 );

  
forint i = 0; i < 5; i++ )
  
{
   events[i] 
= new ManualResetEvent( false );
   FileThread thdSub 
= new FileThread( 
    i 
* nTotalBytes,
    ( fi.Length 
- i * nTotalBytes ) > nTotalBytes ? nTotalBytes:(int)( fi.Length - i * nTotalBytes ), fi.FullName );
   ThreadPool.QueueUserWorkItem( 
new WaitCallback( thdSub.UploadFile ), events[i] );
  }


  
//Wait for threads finished
  WaitHandle.WaitAll( events );

  
//Reset button status
  btnUpload.Enabled = true;
 }


 

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

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

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

//

 

---------------------------  Multi - thread Upload Demo  ---------------------------------------
// --------------------------------------------------------------------------------------------
// ---File:    frmUpload
// ---Description:   The multi-thread upload form file to demenstrate howto use multi-thread to 
//       upload files
// ---Author:  Knight
// ---Date:    Oct.12, 2006
// --------------------------------------------------------------------------------------------
// ---------------------------{Multi-thread Upload Demo}--------------------------------------- 


using  System;
using  System.Drawing;
using  System.Collections;
using  System.ComponentModel;
using  System.Windows.Forms;
using  System.Data;

namespace  CSUpload
{
 
using System.IO;
 
using System.Diagnostics;
 
using System.Threading;
 
using WSUploadFile;//Web-service reference namespace

 
/// 
 
/// Summary description for Form1.
 
/// 

 public class frmUpload : System.Windows.Forms.Form
 
{
  
private System.Windows.Forms.TextBox txtFileName;
  
private System.Windows.Forms.Button btnBrowse;
  
private System.Windows.Forms.Button btnUpload;

  
/// 
  
/// Required designer variable.
  
/// 

  private System.ComponentModel.Container components = null;

  
public frmUpload()
  
{
   
//
   
// Required for Windows Form Designer support
   
//


InitializeComponent(); 

   
//
   
// TODO: Add any constructor code after InitializeComponent call
   
//
  }


  
/// 
  
/// Clean up any resources being used.
  
/// 

  protected override void Dispose( bool disposing )
  
{
   
if( disposing )
   
{
    
if (components != null
    
{
     components.Dispose();
    }

   }

   
base.Dispose( disposing );
  }


  
Windows Form Designer generated code
  
/// 
  
/// The main entry point for the application.
  
/// 

  static void Main() 
  
{
   Application.Run(
new frmUpload());
  }

 
  
private FileUpload myUpload = new FileUpload();

  
private void UploadData( string FileName, int StartPos, byte[] bData )
  
{
   
//Call web service upload
   myUpload.UploadFileData( FileName, StartPos, bData );
  }


  
private void btnUpload_Click(object sender, System.EventArgs e)
  
{
   FileInfo fi 
= new FileInfo( txtFileName.Text );
   
if( fi.Exists )
   
{
    btnUpload.Enable

= false;//Avoid upload twice 

    
//Init signals
    ManualResetEvent[] events = new ManualResetEvent[5];

    
//Devide blocks
    int nTotalBytes = (int)( fi.Length / 5 );

    
forint i = 0; i < 5; i++ )
    
{
     events[i] 
= new ManualResetEvent( false );
     FileThread thdSub 
= new FileThread( 
      i 
* nTotalBytes,
      ( fi.Length 
- i * nTotalBytes ) > nTotalBytes ? nTotalBytes:(int)( fi.Length - i * nTotalBytes ), fi.FullName );
     ThreadPool.QueueUserWorkItem( 
new WaitCallback( thdSub.UploadFile ), events[i] );
    }

 
    
//Wait for threads finished
    WaitHandle.WaitAll( events );
 
    
//Reset button status
    btnUpload.Enabled = true;
   }

 
  }


  
private void frmUpload_Load(object sender, System.EventArgs e)
  
{
   FileThread.UploadHandle 
= new UploadFileData( this.UploadData );
  }


  
private void btnBrowse_Click(object sender, System.EventArgs e)
  
{
   
if( fileOpen.ShowDialog() == DialogResult.OK )
    txtFileName.Text 
= fileOpen.FileName;
  }


  
private OpenFileDialog fileOpen = new OpenFileDialog();
 }


 

 
public delegate void UploadFileData( string FileName, int StartPos, byte[] bData );
 
/// 
 
/// FileThread: a class for sub-thread
 
/// 

 sealed class FileThread
 
{
  
private int nStartPos;
  
private int nTotalBytes;
  
private string strFileName;
  
public static UploadFil

eData UploadHandle; 

  
/// 
  
/// Constructor
  
/// 
  
/// 
  
/// 
  
/// 

  public FileThread( int StartPos, int TotalBytes, string FileName )
  
{
   
//Init thread variant
   nStartPos = StartPos;
   nTotalBytes 
= TotalBytes;
   strFileName 
= FileName;
 
   
//Only for debug
   Debug.WriteLine( string.Format( "File name:{0} position: {1} total byte:{2}", strFileName, nStartPos, nTotalBytes ) );
  }


  
/// 
  
/// Sub-thread entry function 
  
/// 
  
/// 

  public void UploadFile( object stateinfo )
  
{
   
int nRealRead, nBufferSize;
   
const int BUFFER_SIZE = 10240;

   
using( FileStream fs = new FileStream( strFileName, FileMode.Open, FileAccess.Read, FileShare.Read ) )
   
{
    
string sName = strFileName.Substring( strFileName.LastIndexOf( "/" ) + 1 );
    
byte[] bBuffer = new byte[BUFFER_SIZE];//Init 10k buffer
    fs.Position = nStartPos;
    nRealRead 
= 0;

    
do
    
{
     nBufferSize 
= BUFFER_SIZE;
     
if( nRealRead + BUFFER_SIZE > nTotalBytes )
      nBufferSize 
= nTotalBytes - nRealRead;

     nBufferSize 
= fs.Read( bBuffer, 0, nBufferSize );

    
if( nBufferSize == BUFFER_SIZE )
      UploadHandle( sName, nRealRead 
+ nStartPos, bBuffer );

     
else if( nBufferSize > 0 )
     
{

      
//Copy data 
      byte[] bytData = new byte[nBufferSize];

      Array.Copy( bBuffer,
0, bytData, 0, nBufferSize );

      UploadHandle( sName, nRealRead 
+ nStartPos, bytData );
     }
 


     nRealRead 
+= nBufferSize;
    }


    
while( nRealRead < nTotalBytes );
   }


   
//Release signal
   ManualResetEvent mr = stateinfo as ManualResetEvent;

   
if( mr != null )
    mr.Set();
  }

 }

}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值