借助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,bData.Length ); ??? } ??? return true; } ? 其中“Uploads”是在服务程序所在目录下的一个子目录,需要设置ASPNET用户对此目录具有可写权限。 ? 相对于服务器端来说,客户端要稍微复杂一些,因为要牵扯到多线程的问题。为了更好的传递参数,我用一个线程类来完成。具体如下。 ??? 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,nBufferSize ); ??????????????????? if( nBufferSize == BUFFER_SIZE ) ??????????????????????? UploadHandle( sName, ??????????????????????????? nRealRead + nStartPos, ??????????????????????????? bBuffer ); ??????????????????? else if( nBufferSize > 0 ) ??????????????????? { ??????????????????????? //Copy data ??????????????????????? byte[] bytData = new byte[nBufferSize]; ??????????????????????? Array.Copy( bBuffer,bytData,nBufferSize ); ??????????????????????? UploadHandle( sName, ??????????????????????????? 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 ); ??????? 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; ??? } ? 总体来说,程序还是相对比较简单,而我也只是做了个简单例子而已,一些细节都没有进行处理。 ? 本来想打包提供给大家下载,没想到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> ??? /// 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,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, ??????????????????????????? bytData ); ??????????????????? } ??????????????????? nRealRead += nBufferSize; ??????????????? } ??????????????? while( nRealRead < nTotalBytes ); ??????????? } ??????????? //Release signal ??????????? ManualResetEvent mr = stateinfo as ManualResetEvent; ??????????? if( mr != null ) ??????????????? mr.Set(); ??????? } ??? } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |