微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

借助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;

    }

 

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

 

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

如下是客户端的完整代码

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

        }

    }

 

}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐