WEB开发网
开发学院WEB开发ASP.NET 借助WebService实现多线程上传文件 阅读

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

 2008-12-12 17:24:54 来源:WEB开发网   
核心提示:在WebService的帮助下,进行多线程上传文件是非常简单,借助WebService实现多线程上传文件,因此我只做个简单的例子,那么如果想要实现此功能的朋友,而我也只是做了个简单例子而已,一些细节都没有进行处理,可以在我的基础上进行扩展,首先说说服务器端

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

首先说说服务器端,只需要提供一个能允许多线程写文件的函数即可,具体代码如下。view plaincopy to clipboardPRint?
[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; 
 

[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用户对此目录具有可写权限。
  相对于服务器端来说,客户端要稍微复杂一些,因为要牵扯到多线程的问题。为了更好的传递参数,我用一个线程类来完成。具体如下。view plaincopy to clipboardprint?
public delegate void UploadFileData( string FileName, int StartPos, byte[] bData ); 
 
 
 
/// <summary> 
 
/// FileThread: a class for sub-thread 
 
/// </summary> 
 
sealed class FileThread 
 
{ 
 
private int nStartPos; 
 
private int nTotalBytes; 
 
private string strFileName; 
 
public static UploadFileData UploadHandle; 
 
 
 
/// <summary> 
 
/// Constructor 
 
/// </summary> 
 
/// <param name="StartPos"></param> 
 
/// <param name="TotalBytes"></param> 
 
/// <param name="FileName"></param> 
 
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 ) ); 
 
} 
 
 
 
/// <summary> 
 
/// Sub-thread entry function  
 
/// </summary> 
 
/// <param name="stateinfo"></param> 
 
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(); 
 
} 
 

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

 /// <summary>

 /// FileThread: a class for sub-thread

 /// </summary>

 sealed class FileThread

 {

 private int nStartPos;

 private int nTotalBytes;

 private string strFileName;

 public static UploadFileData UploadHandle;

 /// <summary>

 /// Constructor

 /// </summary>

 /// <param name="StartPos"></param>

 /// <param name="TotalBytes"></param>

 /// <param name="FileName"></param>

 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 ) );

 }

 /// <summary>

 /// Sub-thread entry function

 /// </summary>

 /// <param name="stateinfo"></param>

 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();

 }

 }  那么在执行的时候,要创建线程类对象,并为每一个每个线程设置一个信号量,从而能在所有线程都结束的时候得到通知,大致的代码如下。view plaincopy to clipboardprint?
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 ); 
 
for( int 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; 
 

 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 );

 for( int 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;

 }  总体来说,程序还是相对比较简单,而我也只是做了个简单例子而已,一些细节都没有进行处理。
  如下是客户端的完整代码。view plaincopy to clipboardprint?
//--------------------------- 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> 
 
 /// Summary description for Form1. 
 
 /// </summary> 
 
 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; 
 
 /// <summary> 
 
 /// Required designer variable. 
 
 /// </summary> 
 
 private System.ComponentModel.Container components = null; 
 
  
 
 public frmUpload() 
 
 { 
 
 // 
 
 // Required for Windows Form Designer support 
 
 // 
 
 InitializeComponent(); 
 
  
 
 // 
 
 // TODO: Add any constructor code after InitializeComponent call 
 
 // 
 
 } 
 
  
 
 /// <summary> 
 
 /// Clean up any resources being used. 
 
 /// </summary> 
 
 protected override void Dispose( bool disposing ) 
 
 { 
 
 if( disposing ) 
 
 { 
 
 if (components != null)  
 
 { 
 
 components.Dispose(); 
 
 } 
 
 } 
 
 base.Dispose( disposing ); 
 
 } 
 
 
 
 #region Windows Form Designer generated code 
 
 /// <summary> 
 
 /// Required method for Designer support - do not modify 
 
 /// the contents of this method with the code editor. 
 
 /// </summary> 
 
 private void InitializeComponent() 
 
 { 
 
 this.txtFileName = new System.Windows.Forms.TextBox(); 
 
 this.btnBrowse = new System.Windows.Forms.Button(); 
 
 this.btnUpload = new System.Windows.Forms.Button(); 
 
 this.SuspendLayout(); 
 
 //  
 
 // txtFileName 
 
 //  
 
 this.txtFileName.Location = new System.Drawing.Point(16, 24); 
 
 this.txtFileName.Name = "txtFileName"; 
 
 this.txtFileName.Size = new System.Drawing.Size(248, 20); 
 
 this.txtFileName.TabIndex = 0; 
 
 this.txtFileName.Text = ""; 
 
 //  
 
 // btnBrowse 
 
 //  
 
 this.btnBrowse.Location = new System.Drawing.Point(272, 24); 
 
 this.btnBrowse.Name = "btnBrowse"; 
 
 this.btnBrowse.TabIndex = 1; 
 
 this.btnBrowse.Text = "&Browse..."; 
 
 this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click); 
 
 //  
 
 // btnUpload 
 
 //  
 
 this.btnUpload.Location = new System.Drawing.Point(272, 56); 
 
 this.btnUpload.Name = "btnUpload"; 
 
 this.btnUpload.TabIndex = 2; 
 
 this.btnUpload.Text = "&Upload"; 
 
 this.btnUpload.Click += new System.EventHandler(this.btnUpload_Click); 
 
 //  
 
 // frmUpload 
 
 //  
 
 this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); 
 
 this.ClientSize = new System.Drawing.Size(370, 111); 
 
 this.Controls.Add(this.btnUpload); 
 
 this.Controls.Add(this.btnBrowse); 
 
 this.Controls.Add(this.txtFileName); 
 
 this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 
 
 this.MaximizeBox = false; 
 
 this.Name = "frmUpload"; 
 
 this.Text = "Upload"; 
 
 this.Load += new System.EventHandler(this.frmUpload_Load); 
 
 this.ResumeLayout(false); 
 
  
 
 } 
 
 #endregion 
 
  
 
 /// <summary> 
 
 /// The main entry point for the application. 
 
 /// </summary> 
 
 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.Enabled = false;//Avoid upload twice 
 
  
 
 //Init signals 
 
 ManualResetEvent[] events = new ManualResetEvent[5]; 
 
  
 
 //Devide blocks 
 
 int nTotalBytes = (int)( fi.Length / 5 ); 
 
 for( int 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 ); 
 
  
 
 /// <summary> 
 
 /// FileThread: a class for sub-thread 
 
 /// </summary> 
 
 sealed class FileThread 
 
 { 
 
 private int nStartPos; 
 
 private int nTotalBytes; 
 
 private string strFileName; 
 
 public static UploadFileData UploadHandle; 
 
  
 
 /// <summary> 
 
 /// Constructor 
 
 /// </summary> 
 
 /// <param name="StartPos"></param> 
 
 /// <param name="TotalBytes"></param> 
 
 /// <param name="FileName"></param> 
 
 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 ) ); 
 
 } 
 
  
 
 /// <summary> 
 
 /// Sub-thread entry function  
 
 /// </summary> 
 
 /// <param name="stateinfo"></param> 
 
 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(); 
 
 } 
 
 } 
 
  
 
}

Tags:借助 WebService 实现

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接