zoukankan      html  css  js  c++  java
  • 借助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 );

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

            }

        }

     

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

        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;

        }

     

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

     

    本来想打包提供给大家下载,没想到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, 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 );

     

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

     

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

     

            }

     

        }

     

    }

     

  • 相关阅读:
    asp.net 获取当前项目的根目录路径
    asp.net 中 UEditor 图片和附件上传失败的处理方法
    [LOJ#2331]「清华集训 2017」某位歌姬的故事
    [LOJ#2330]「清华集训 2017」榕树之心
    [LOJ#2329]「清华集训 2017」我的生命已如风中残烛
    [LOJ#2328]「清华集训 2017」避难所
    [LOJ#2327]「清华集训 2017」福若格斯
    [LOJ#2326]「清华集训 2017」简单数据结构
    [LOJ#2325]「清华集训 2017」小Y和恐怖的奴隶主
    [LOJ#2324]「清华集训 2017」小Y和二叉树
  • 原文地址:https://www.cnblogs.com/zhwl/p/2392064.html
Copyright © 2011-2022 走看看