·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> ASP.NET网站开发 >> 借助WebService实现多线程上传文件

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

作者:佚名      ASP.NET网站开发编辑:admin      更新时间:2022-07-23

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