【轉】C#下帶進度條的FTP上傳類


該類轉自:http://blog.csdn.net/byshome/article/details/5801991,稍作修改

using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Globalization;
using System.Text.RegularExpressions;

namespace FTP
{
    public class FTPHelper : IDisposable
    {
        #region 聲明事件
        /// <summary>
        /// 正在下載文件
        /// </summary>
        public event FTPSendEventHandler FileDownloading;
        private delegate void OnFileDownloadingDelegate(FTPConnect ftpConnect, long lTotalBytes, long lBytesTransfered);
        /// <summary>
        /// 正在下載文件封裝模式
        /// </summary>
        private void OnFileDownloading(FTPConnect ftpConnect, long lTotalBytes, long lBytesTransfered)
        {
            if (this.FileDownloading != null)
            {
                if (lBytesTransfered > lTotalBytes)
                    lBytesTransfered = lTotalBytes;
                System.ComponentModel.ISynchronizeInvoke aSynch = this.FileDownloading.Target as System.ComponentModel.ISynchronizeInvoke;
                if (aSynch != null && aSynch.InvokeRequired)
                    aSynch.Invoke(new OnFileDownloadingDelegate(OnFileDownloading), new object[] { ftpConnect, lTotalBytes, lBytesTransfered });
                else
                    this.FileDownloading(ftpConnect, new FTPSendEventArgs(lTotalBytes, lBytesTransfered));
            }
        }
        /// <summary>
        /// 文件下載完成
        /// </summary>
        public event EventHandler FileDownloadCompleted;
        private delegate void OnFileDownloadCompletedDelegate(FTPConnect ftpConnect);
        /// <summary>
        /// 文件下載完成封裝模式
        /// </summary>
        private void OnFileDownloadCompleted(FTPConnect ftpConnect)
        {
            if (this.FileDownloadCompleted != null)
            {
                System.ComponentModel.ISynchronizeInvoke aSynch = this.FileDownloadCompleted.Target as System.ComponentModel.ISynchronizeInvoke;
                if (aSynch != null && aSynch.InvokeRequired)
                    aSynch.Invoke(new OnFileDownloadCompletedDelegate(OnFileDownloadCompleted), new object[] { ftpConnect });
                else
                    this.FileDownloadCompleted(ftpConnect, new EventArgs());
            }
        }
        /// <summary>
        /// 取消正在下載的文件
        /// </summary>
        public event EventHandler FileDownloadCanceled;
        private delegate void OnFileDownloadCanceledDelegate(FTPConnect ftpConnect);
        /// <summary>
        /// 取消正在下載的文件封裝模式
        /// </summary>
        private void OnFileDownloadCanceled(FTPConnect ftpConnect)
        {
            if (this.FileDownloadCanceled != null)
            {
                System.ComponentModel.ISynchronizeInvoke aSynch = this.FileDownloadCanceled.Target as System.ComponentModel.ISynchronizeInvoke;
                if (aSynch != null && aSynch.InvokeRequired)
                    aSynch.Invoke(new OnFileDownloadCanceledDelegate(OnFileDownloadCanceled), new object[] { ftpConnect });
                else
                    this.FileDownloadCanceled(ftpConnect, new EventArgs());
            }
        }
        /// <summary>
        /// 正在上傳文件
        /// </summary>
        public event FTPSendEventHandler FileUploading;
        private delegate void OnFileUploadingDelegate(FTPConnect ftpConnect, long lTotalBytes, long lBytesTransfered);
        /// <summary>
        /// 正在下載事件封裝模式
        /// </summary>
        /// <param name="lTotalBytes"></param>
        /// <param name="lBytesTransfered"></param>
        private void OnFileUploading(FTPConnect ftpConnect, long lTotalBytes, long lBytesTransfered)
        {
            if (this.FileUploading != null)
            {
                if (lBytesTransfered > lTotalBytes)
                    lBytesTransfered = lTotalBytes;
                System.ComponentModel.ISynchronizeInvoke aSynch = this.FileUploading.Target as System.ComponentModel.ISynchronizeInvoke;
                if (aSynch != null && aSynch.InvokeRequired)
                    aSynch.Invoke(new OnFileUploadingDelegate(OnFileUploading), new object[] { ftpConnect, lTotalBytes, lBytesTransfered });
                else
                    this.FileUploading(ftpConnect, new FTPSendEventArgs(lTotalBytes, lBytesTransfered));
            }
        }
        /// <summary>
        /// 文件上傳完成
        /// </summary>
        public event EventHandler FileUploadCompleted;
        private delegate void OnFileUploadCompletedDelegate(FTPConnect ftpConnect);
        private void OnFileUploadCompleted(FTPConnect ftpConnect)
        {
            if (this.FileUploadCompleted != null)
            {
                System.ComponentModel.ISynchronizeInvoke aSynch = this.FileUploadCompleted.Target as System.ComponentModel.ISynchronizeInvoke;
                if (aSynch != null && aSynch.InvokeRequired)
                    aSynch.Invoke(new OnFileUploadCompletedDelegate(OnFileUploadCompleted), new object[] { ftpConnect });
                else
                    this.FileUploadCompleted(ftpConnect, new EventArgs());
            }
        }
        /// <summary>
        /// 取消了上傳文件
        /// </summary>
        public event EventHandler FileUploadCanceled;
        private delegate void OnFileUploadCanceledDelegate(FTPConnect ftpConnect);
        private void OnFileUploadCanceled(FTPConnect ftpConnect)
        {
            if (this.FileUploadCanceled != null)
            {
                System.ComponentModel.ISynchronizeInvoke aSynch = this.FileUploadCanceled.Target as System.ComponentModel.ISynchronizeInvoke;
                if (aSynch != null && aSynch.InvokeRequired)
                    aSynch.Invoke(new OnFileUploadCanceledDelegate(OnFileUploadCanceled), new object[] { ftpConnect });
                else
                    this.FileUploadCanceled(ftpConnect, new EventArgs());
            }
        }
        /// <summary>
        /// 傳輸過程發生錯誤事件
        /// </summary>
        public event FTPErrorEventHandler FtpError;
        private delegate void OnFtpErrorDelegate(FTPConnect ftpConnect, Exception error);
        public void OnFtpError(FTPConnect ftpConnect, Exception error)
        {
            if (this.FtpError != null)
            {
                System.ComponentModel.ISynchronizeInvoke aSynch = this.FtpError.Target as System.ComponentModel.ISynchronizeInvoke;
                if (aSynch != null && aSynch.InvokeRequired)
                    aSynch.Invoke(new OnFtpErrorDelegate(OnFtpError), new object[] { ftpConnect, error });
                else
                    this.FtpError(ftpConnect, new FTPErrorEventArgs(error));
            }
        }
        #endregion
        #region FTPUrl結構
        public class FTPUrl
        {
            private string m_Url = String.Empty;
            private string m_RemoteHost = String.Empty;
            private IPAddress m_RemoteHostIP = IPAddress.None;
            private int m_RemotePort = 21;
            private string m_UserName = String.Empty;
            private string m_Password = String.Empty;
            private string m_SubUrl = String.Empty;
            public FTPUrl()
            { }
            public FTPUrl(string url)
            {
                this.Url = url;
            }
            /// <summary>
            /// FTP的全地址
            /// </summary>
            public string Url
            {
                get { return this.m_Url; }
                set
                {
                    if (value.IndexOf("@") < 0)
                        throw (new Exception("FTP地址路徑不合法!格式應為ftp://用戶名:密碼@地址[:端口]/"));
                    string strSubUrl = "";
                    string strRemoteHostAndPort = value.Substring(value.IndexOf("@") + 1);
                    if (strRemoteHostAndPort.IndexOf("/") > 0)
                    {
                        strSubUrl = strRemoteHostAndPort.Substring(strRemoteHostAndPort.IndexOf("/"));
                        strRemoteHostAndPort = strRemoteHostAndPort.Substring(0, strRemoteHostAndPort.IndexOf("/"));
                    }
                    string strRemoteHost = strRemoteHostAndPort;
                    int iRemotePort = 21;
                    if (strRemoteHostAndPort.IndexOf(":") > 0)
                    {
                        strRemoteHost = strRemoteHostAndPort.Substring(0, strRemoteHostAndPort.IndexOf(":"));
                        string strRemotePort = strRemoteHostAndPort.Substring(strRemoteHostAndPort.IndexOf(":") + 1);
                        if (!int.TryParse(strRemotePort, out iRemotePort))
                            iRemotePort = 21;
                    }
                    string strUserNameAndPassword = value.Substring(0, value.IndexOf("@")).Trim();
                    if (strUserNameAndPassword.ToLower().StartsWith("ftp://"))
                        strUserNameAndPassword = strUserNameAndPassword.Substring(6).Trim();
                    if (strUserNameAndPassword == string.Empty || strUserNameAndPassword.IndexOf(":") < 0)
                        throw (new Exception("FTP地址路徑不合法!格式應為ftp://用戶名:密碼@地址[:端口]/"));
                    string strUserName = strUserNameAndPassword.Substring(0, strUserNameAndPassword.IndexOf(":"));
                    string strPassword = strUserNameAndPassword.Substring(strUserNameAndPassword.IndexOf(":") + 1);

                    IPAddress[] ips = Dns.GetHostAddresses(strRemoteHost);
                    if (ips.Length == 0)
                        throw (new Exception("FTP地址路徑中主機地址無效!"));
                    strSubUrl = strSubUrl.Replace("//", "/");
                    this.m_RemoteHostIP = ips[0];
                    this.m_RemoteHost = strRemoteHost;
                    this.m_RemotePort = iRemotePort;
                    this.m_UserName = strUserName;
                    this.m_Password = strPassword;
                    this.m_SubUrl = strSubUrl;
                    this.m_Url = value;
                }
            }
            /// <summary>
            /// 主機地址
            /// </summary>
            public string RemoteHost
            {
                get { return this.m_RemoteHost; }
            }
            /// <summary>
            /// 主機IP
            /// </summary>
            public IPAddress RemoteHostIP
            {
                get { return this.m_RemoteHostIP; }
            }
            /// <summary>
            /// 主機端口
            /// </summary>
            public int RemotePort
            {
                get { return this.m_RemotePort; }
            }
            public string UserName
            {
                get { return this.m_UserName; }
            }
            public string Password
            {
                get { return this.m_Password; }
            }
            public string SubUrl
            {
                get { return this.m_SubUrl; }
            }
        }
        #endregion
        #region 傳輸模式
        /// <summary>
        /// 傳輸模式:二進制類型、ASCII類型
        /// </summary>
        public enum TransferType
        {
            /// <summary>
            /// Binary
            /// </summary>
            Binary,
            /// <summary>
            /// ASCII
            /// </summary>
            ASCII
        };
        #endregion
        #region 存貯FTP的連接結構類
        public class FTPConnect
        {
            #region 私有字段
            /// <summary>
            /// 數據傳送套接字列表
            /// </summary>
            private List<Socket> m_DataSocketList;
            private string m_ID;
            /// <summary>
            /// 唯一ID
            /// </summary>
            public string ID
            {
                get { return this.m_ID; }
            }
            private object m_Tag = null;
            /// <summary>
            /// 擴展標記
            /// </summary>
            public object Tag
            {
                get { return this.m_Tag; }
                set { this.m_Tag = value; }
            }
            private bool m_DataTransmitting = false;
            /// <summary>
            /// 數據正在傳輸 標記
            /// </summary>
            public bool DataTransmitting
            {
                get { return this.m_DataTransmitting; }
                set { this.m_DataTransmitting = value; }
            }
            private Socket m_SocketControl;
            /// <summary>
            /// FTPUrl
            /// </summary>
            private FTPUrl m_FTPUrl;
            /// <summary>
            /// 是否已經連接
            /// </summary>
            private bool m_IsConnected;
            private Encoding m_EncodeType = Encoding.Default;
            /// <summary>
            /// 編碼方式
            /// </summary>
            public Encoding EncodeType
            {
                get { return this.m_EncodeType; }
                set { this.m_EncodeType = value; }
            }
            /// <summary>
            /// 接收和發送數據的緩沖區
            /// </summary>
            private static int BLOCK_SIZE = 512;
            /// <summary>
            /// 緩沖區大小
            /// </summary>
            private Byte[] m_Buffer;
            public Byte[] Buffer
            {
                get { return this.m_Buffer; }
                set { this.m_Buffer = value; }
            }
            private string m_Message;
            /// <summary>
            /// 當前的消息
            /// </summary>
            public string Message
            {
                get { return this.m_Message; }
                set { this.m_Message = value; }
            }
            private string m_ReplyString;
            /// <summary>
            /// 應答字符串
            /// </summary>
            public string ReplyString
            {
                get { return this.m_ReplyString; }
                set { this.m_ReplyString = value; }
            }
            private int m_ReplyCode;
            /// <summary>
            /// 應答代碼
            /// </summary>
            public int ReplyCode
            {
                get { return this.m_ReplyCode; }
                set { this.m_ReplyCode = value; }
            }
            /// <summary>
            /// 傳輸模式
            /// </summary>
            private TransferType trType;
            #endregion
            public FTPConnect()
            {
                this.m_ID = System.Guid.NewGuid().ToString();
                this.m_DataSocketList = new List<Socket>();
                this.m_Buffer = new Byte[BLOCK_SIZE];
            }
            public FTPConnect(FTPUrl ftpUrl)
            {
                this.m_ID = System.Guid.NewGuid().ToString();
                this.m_DataSocketList = new List<Socket>();
                this.m_Buffer = new Byte[BLOCK_SIZE];
                this.FTPUrl = ftpUrl;
            }
            public FTPConnect(FTPUrl ftpUrl, string ftpId)
            {
                if (String.IsNullOrEmpty(ftpId))
                    ftpId = System.Guid.NewGuid().ToString();
                this.m_ID = ftpId;
                this.m_DataSocketList = new List<Socket>();
                this.m_Buffer = new Byte[BLOCK_SIZE];
                this.FTPUrl = ftpUrl;
            }
            #region 公共字段
            /// <summary>
            /// 套接字連接
            /// </summary>
            public Socket SocketControl
            {
                get { return this.m_SocketControl; }
                set { this.m_SocketControl = value; }
            }
            /// <summary>
            /// 對應的URL
            /// </summary>
            public FTPUrl FTPUrl
            {
                get { return this.m_FTPUrl; }
                set { this.m_FTPUrl = value; }
            }
            /// <summary>
            /// 是否已經連接
            /// </summary>
            public bool IsConnected
            {
                get { return this.m_IsConnected; }
                set { this.m_IsConnected = value; }
            }
            #endregion
            #region 公共方法
            #region 取消傳送數據
            public void CancelDataTransmit()
            {
                this.m_DataTransmitting = false;
            }
            #endregion
            #region 發送命令
            /// <summary>
            /// 發送命令並獲取應答碼和最后一行應答字符串
            /// </summary>
            /// <param name="strCommand">命令</param>
            public void SendCommand(string strCommand)
            {
                if (this.m_SocketControl == null)
                    throw (new Exception("請先連接服務器再進行操作!"));
                Byte[] cmdBytes = m_EncodeType.GetBytes((strCommand + "\r\n").ToCharArray());
                this.m_SocketControl.Send(cmdBytes, cmdBytes.Length, 0);
                this.ReadReply();
            }
            #endregion
            #region 讀取最后一行的消息
            /// <summary>
            /// 讀取Socket返回的所有字符串
            /// </summary>
            /// <returns>包含應答碼的字符串行</returns>
            private string ReadLine()
            {
                if (this.m_SocketControl == null)
                    throw (new Exception("請先連接服務器再進行操作!"));
                while (true)
                {
                    int iBytes = this.m_SocketControl.Receive(m_Buffer, m_Buffer.Length, 0);
                    m_Message += m_EncodeType.GetString(m_Buffer, 0, iBytes);
                    if (iBytes < m_Buffer.Length)
                    {
                        break;
                    }
                }
                char[] seperator = { '\n' };
                string[] mess = m_Message.Split(seperator);
                if (m_Message.Length > 2)
                {
                    m_Message = mess[mess.Length - 2];
                    //seperator[0]是10,換行符是由13和0組成的,分隔后10后面雖沒有字符串,
                    //但也會分配為空字符串給后面(也是最后一個)字符串數組,
                    //所以最后一個mess是沒用的空字符串
                    //但為什么不直接取mess[0],因為只有最后一行字符串應答碼與信息之間有空格
                }
                else
                {
                    m_Message = mess[0];
                }
                if (!m_Message.Substring(3, 1).Equals(" "))//返回字符串正確的是以應答碼(如220開頭,后面接一空格,再接問候字符串)
                {
                    return this.ReadLine();
                }
                return m_Message;
            }
            #endregion
            #region 讀取應答代碼
            /// <summary>
            /// 將一行應答字符串記錄在strReply和strMsg
            /// 應答碼記錄在iReplyCode
            /// </summary>
            public void ReadReply()
            {
                this.m_Message = "";
                this.m_ReplyString = this.ReadLine();
                this.m_ReplyCode = Int32.Parse(m_ReplyString.Substring(0, 3));
            }
            #endregion
            #region 斷開連接
            /// <summary>
            /// 關閉連接
            /// </summary>
            public void DisConnect()
            {
                this.m_DataTransmitting = false;
                while (this.m_DataSocketList.Count > 0)
                {
                    Socket socket = this.m_DataSocketList[0];
                    if (socket != null && socket.Connected)
                        socket.Close();
                    this.m_DataSocketList.RemoveAt(0);
                }
                if (this.m_IsConnected && this.m_SocketControl != null)
                    this.SendCommand("QUIT");
                this.CloseSocketConnect();
                this.m_Buffer = null;
            }
            /// <summary>
            /// 關閉socket連接(用於登錄以前)
            /// </summary>
            private void CloseSocketConnect()
            {
                if (this.m_SocketControl != null && this.m_SocketControl.Connected)
                {
                    this.m_SocketControl.Close();
                    this.m_SocketControl = null;
                }
                this.m_IsConnected = false;
            }
            #endregion
            #region 連接服務器
            public void Connect()
            {
                this.DisConnect();//先斷開現有連接
                this.m_Buffer = new byte[BLOCK_SIZE];
                this.m_SocketControl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint ep = new IPEndPoint(this.m_FTPUrl.RemoteHostIP, this.m_FTPUrl.RemotePort);
                try
                {
                    this.m_SocketControl.Connect(ep);
                }
                catch (Exception)
                {
                    throw new IOException(String.Format("無法連接到遠程服務器{0}!", this.m_FTPUrl.RemoteHost));
                }
                // 獲取應答碼
                this.ReadReply();
                if (m_ReplyCode != 220)
                {
                    this.DisConnect();
                    throw new IOException(m_ReplyString.Substring(4));
                }
                // 登陸
                this.SendCommand("USER " + this.m_FTPUrl.UserName);
                if (!(m_ReplyCode == 331 || m_ReplyCode == 230))
                {
                    this.CloseSocketConnect();//關閉連接
                    throw new IOException(m_ReplyString.Substring(4));
                }
                if (m_ReplyCode != 230)
                {
                    this.SendCommand("PASS " + this.m_FTPUrl.Password);
                    if (!(m_ReplyCode == 230 || m_ReplyCode == 202))
                    {
                        this.CloseSocketConnect();//關閉連接
                        throw new IOException(m_ReplyString.Substring(4));
                    }
                }
                this.m_IsConnected = true;
            }
            #endregion
            #region 改變目錄
            /// <summary>
            /// 改變目錄
            /// </summary>
            /// <param name="strDirName">新的工作目錄名</param>
            public void ChangeDir(string dirName)
            {
                if (!this.m_IsConnected)
                    throw (new Exception("請先連接服務器然后再進行CWD操作!"));
                if (dirName.Equals(".") || dirName.Equals(""))
                    return;
                this.SendCommand("CWD " + dirName);
                if (m_ReplyCode != 250)
                    throw new IOException(m_ReplyString.Substring(4));
            }
            #endregion
            #region 傳輸模式
            /// <summary>
            /// 設置傳輸模式
            /// </summary>
            /// <param name="ttType">傳輸模式</param>
            public void SetTransferType(TransferType ttType)
            {
                if (ttType == TransferType.Binary)
                {
                    this.SendCommand("TYPE I");//binary類型傳輸
                }
                else
                {
                    this.SendCommand("TYPE A");//ASCII類型傳輸
                }
                if (m_ReplyCode != 200)
                {
                    throw new IOException(m_ReplyString.Substring(4));
                }
                else
                {
                    trType = ttType;
                }
            }
            /// <summary>
            /// 獲得傳輸模式
            /// </summary>
            /// <returns>傳輸模式</returns>
            public TransferType GetTransferType()
            {
                return trType;
            }
            #endregion
            #region 建立進行數據連接的socket
            /// <summary>
            /// 建立進行數據連接的socket
            /// </summary>
            /// <returns>數據連接socket</returns>
            public Socket CreateDataSocket()
            {
                this.SendCommand("PASV");
                if (this.m_ReplyCode != 227)
                    throw new IOException(this.m_ReplyString.Substring(4));
                int index1 = this.m_ReplyString.IndexOf('(');
                int index2 = this.m_ReplyString.IndexOf(')');
                string ipData = this.m_ReplyString.Substring(index1 + 1, index2 - index1 - 1);
                int[] parts = new int[6];
                int len = ipData.Length;
                int partCount = 0;
                string buf = "";
                for (int i = 0; i < len && partCount <= 6; i++)
                {
                    char ch = Char.Parse(ipData.Substring(i, 1));
                    if (Char.IsDigit(ch))
                        buf += ch;
                    else if (ch != ',')
                    {
                        throw new IOException("Malformed PASV Reply: " + this.m_ReplyString);
                    }
                    if (ch == ',' || i + 1 == len)
                    {
                        try
                        {
                            parts[partCount++] = Int32.Parse(buf);
                            buf = "";
                        }
                        catch (Exception)
                        {
                            throw new IOException("Malformed PASV Reply: " + this.m_ReplyString);
                        }
                    }
                }
                string ipAddress = parts[0] + "." + parts[1] + "." + parts[2] + "." + parts[3];
                int port = (parts[4] << 8) + parts[5];
                Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ipAddress), port);
                try
                {
                    socket.Connect(ep);
                }
                catch (Exception)
                {
                    throw new IOException(String.Format("無法連接到遠程服務器{0}:{1}!", ipAddress, port));
                }
                this.m_DataSocketList.Add(socket);
                return socket;
            }
            #endregion
            #endregion
        }
        #endregion
        #region 變量區
        /// <summary>
        /// 進行控制連接的socket
        /// </summary>
        private List<FTPConnect> m_FTPConnectList;
        private object m_Tag;
        /// <summary>
        /// 標記
        /// </summary>
        public object Tag
        {
            get { return this.m_Tag; }
            set { this.m_Tag = value; }
        }
        #endregion

        #region 實例化
        public FTPHelper()
        {
            this.m_FTPConnectList = new List<FTPConnect>();
        }
        #endregion
        #region Dispose
        public void Dispose()
        {
            while (this.m_FTPConnectList.Count > 0)
            {
                FTPConnect ftpConnect = this.m_FTPConnectList[0];
                ftpConnect.DisConnect();
                this.m_FTPConnectList.Remove(ftpConnect);
            }
        }
        #endregion
        #region 得到文件大小
        /// <summary>
        /// 得到文件大小
        /// </summary>
        /// <param name="fileUrl">目標文件,包含用戶名與密碼。如:ftp://username:password@127.0.0.1/1.txt</param>
        /// <param name="UserName">用戶名</param>
        /// <param name="Password">密碼</param>
        /// <returns></returns>
        public long GetFileSize(string fileUrl)
        {
            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            try
            {
                ftpUrl = new FTPUrl(fileUrl);
                ftpConnect = new FTPConnect(ftpUrl);
                ftpConnect.Connect();
                string strDirName = ftpUrl.SubUrl;
                if (strDirName.IndexOf("/") >= 0)
                    strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/"));
                ftpConnect.ChangeDir(strDirName);
                ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl));
                long lFileSize = 0;
                if (ftpConnect.ReplyCode == 213)
                    lFileSize = Int64.Parse(ftpConnect.ReplyString.Substring(4));
                else
                    throw new IOException(ftpConnect.ReplyString.Substring(4));
                return lFileSize;
            }
            catch (Exception ex)
            {
                throw (ex);
            }
            finally
            {
                if (ftpConnect != null)
                    ftpConnect.DisConnect();
            }
        }
        #endregion
        #region 得到文件大小
        /// <summary>
        /// 得到文件大小
        /// </summary>
        /// <param name="fileUrl">目標文件,包含用戶名與密碼。如:ftp://username:password@127.0.0.1/1.txt</param>
        /// <param name="UserName">用戶名</param>
        /// <param name="Password">密碼</param>
        /// <returns></returns>
        public DateTime GetDateTimestamp(string fileUrl)
        {
            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            try
            {
                ftpUrl = new FTPUrl(fileUrl);
                ftpConnect = new FTPConnect(ftpUrl);
                ftpConnect.Connect();
                string strDirName = ftpUrl.SubUrl;
                if (strDirName.IndexOf("/") >= 0)
                    strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/"));
                ftpConnect.ChangeDir(strDirName);
                ftpConnect.SendCommand("MDTM " + Path.GetFileName(ftpUrl.SubUrl));
                if (ftpConnect.ReplyCode == 213)
                {
                    string strDateTime = ftpConnect.ReplyString.Substring(4);
                    int iYear = 0, iMonth = 0, iDay = 0, iHour = 0, iMinute = 0, iSecond = 0;
                    if (strDateTime.Length >= 4)
                        int.TryParse(strDateTime.Substring(0, 4), out iYear);
                    if (strDateTime.Length >= 6)
                        int.TryParse(strDateTime.Substring(4, 2), out iMonth);
                    if (strDateTime.Length >= 8)
                        int.TryParse(strDateTime.Substring(6, 2), out iDay);
                    if (strDateTime.Length >= 10)
                        int.TryParse(strDateTime.Substring(8, 2), out iHour);
                    if (strDateTime.Length >= 12)
                        int.TryParse(strDateTime.Substring(10, 2), out iMinute);
                    if (strDateTime.Length >= 14)
                        int.TryParse(strDateTime.Substring(12, 2), out iSecond);
                    return new DateTime(iYear, iMonth, iDay, iHour, iMinute, iSecond).ToLocalTime();
                }
                else
                    throw new IOException(ftpConnect.ReplyString.Substring(4));
            }
            catch (Exception ex)
            {
                throw (ex);
            }
            finally
            {
                if (ftpConnect != null)
                    ftpConnect.DisConnect();
            }
        }
        #endregion
        #region 刪除指定的文件
        /// <summary>
        /// 刪除指定的文件
        /// </summary>
        /// <param name="fileUrl">待刪除文件名</param>
        public void DeleteFile(string fileUrl)
        {
            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            try
            {
                ftpUrl = new FTPUrl(fileUrl);
                ftpConnect = new FTPConnect(ftpUrl);
                ftpConnect.Connect();
                string strDirName = ftpUrl.SubUrl;
                if (strDirName.IndexOf("/") >= 0)
                    strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/"));
                ftpConnect.ChangeDir(strDirName);
                ftpConnect.SendCommand("DELE " + Path.GetFileName(ftpUrl.SubUrl));
                if (ftpConnect.ReplyCode != 250)
                    throw (new Exception(ftpConnect.ReplyString.Substring(4)));
            }
            catch (Exception ex)
            {
                throw (ex);
            }
            finally
            {
                if (ftpConnect != null)
                    ftpConnect.DisConnect();
            }
        }
        #endregion
        #region 重命名
        /// <summary>
        /// 重命名(如果新文件名與已有文件重名,將覆蓋已有文件)
        /// </summary>
        /// <param name="strOldFileName">舊文件名</param>
        /// <param name="strNewFileName">新文件名</param>
        public void Rename(string originalUrl, string newName)
        {
            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            try
            {
                ftpUrl = new FTPUrl(originalUrl);
                ftpConnect = new FTPConnect(ftpUrl);
                ftpConnect.Connect();
                string strDirName = ftpUrl.SubUrl;
                if (strDirName.IndexOf("/") >= 0)
                    strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/"));
                ftpConnect.ChangeDir(strDirName);
                ftpConnect.SendCommand("RNFR " + Path.GetFileName(ftpUrl.SubUrl));
                if (ftpConnect.ReplyCode != 350)
                    throw (new Exception(ftpConnect.ReplyString.Substring(4)));
                ftpConnect.SendCommand("RNTO " + newName);
                if (ftpConnect.ReplyCode != 250)
                    throw (new Exception(ftpConnect.ReplyString.Substring(4)));
            }
            catch (Exception ex)
            {
                throw (ex);
            }
            finally
            {
                if (ftpConnect != null)
                    ftpConnect.DisConnect();
            }
        }
        #endregion
        #region 創建文件夾
        public void MakeDirectory(string dirUrl)
        {
            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            int iCharIndex = 0;
            string strDirUrl, strDirUrlTemp;
            try
            {
                ftpUrl = new FTPUrl(dirUrl);
                ftpConnect = new FTPConnect(ftpUrl);
                ftpConnect.Connect();
                strDirUrl = ftpUrl.SubUrl;
                while (true && strDirUrl.Trim() != "")
                {
                    iCharIndex = strDirUrl.IndexOf("/", iCharIndex) + 1;
                    if (iCharIndex == 0)
                        strDirUrlTemp = strDirUrl;
                    else
                        strDirUrlTemp = strDirUrl.Substring(0, iCharIndex);
                    if (strDirUrlTemp == "")
                        continue;
                    ftpConnect.SendCommand("MKD " + strDirUrlTemp);
                    if (ftpConnect.ReplyCode != 257 && ftpConnect.ReplyCode != 550)
                        throw new IOException(ftpConnect.ReplyString.Substring(4));
                    if (strDirUrlTemp == strDirUrl)
                        break;
                }
            }
            catch (Exception ex)
            {
                throw (ex);
            }
            finally
            {
                if (ftpConnect != null)
                    ftpConnect.DisConnect();
            }
        }
        #endregion
        #region 刪除目錄
        /// <summary>
        /// 刪除目錄
        /// </summary>
        /// <param name="dirUrl">目錄名</param>
        public void RemoveDirectory(string dirUrl)
        {
            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            try
            {
                ftpUrl = new FTPUrl(dirUrl);
                ftpConnect = new FTPConnect(ftpUrl);
                ftpConnect.Connect();
                string strDirPath = ftpUrl.SubUrl;
                string strDirName = ftpUrl.SubUrl;
                if (strDirPath.IndexOf("/") >= 0)
                {
                    strDirPath = strDirPath.Substring(0, strDirPath.LastIndexOf("/"));
                    strDirName = strDirPath.Substring(strDirPath.LastIndexOf("/") + 1);
                }
                ftpConnect.ChangeDir(strDirPath);
                ftpConnect.SendCommand("RMD " + strDirName);
                if (ftpConnect.ReplyCode != 250)
                    throw (new Exception(ftpConnect.ReplyString.Substring(4)));
            }
            catch (Exception ex)
            {
                throw (ex);
            }
            finally
            {
                if (ftpConnect != null)
                    ftpConnect.DisConnect();
            }
        }
        #endregion
        #region 得到簡單的文件列表
        public string[] ListDirectoryFile(string listUrl)
        {
            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            Socket socketData = null;
            try
            {
                ftpUrl = new FTPUrl(listUrl);
                ftpConnect = new FTPConnect(ftpUrl);
                ftpConnect.Connect();
                string strDirPath = ftpUrl.SubUrl;
                if (strDirPath.IndexOf("/") >= 0)
                    strDirPath = strDirPath.Substring(0, strDirPath.LastIndexOf("/"));
                ftpConnect.ChangeDir(strDirPath);
                socketData = ftpConnect.CreateDataSocket();
                ftpConnect.SendCommand("NLST");
                if (ftpConnect.ReplyCode != 150 && ftpConnect.ReplyCode != 125)
                    throw new IOException(ftpConnect.ReplyString.Substring(4));
                //獲得結果
                ftpConnect.Message = "";
                while (true)
                {
                    int iBytes = socketData.Receive(ftpConnect.Buffer, ftpConnect.Buffer.Length, 0);
                    ftpConnect.Message += ftpConnect.EncodeType.GetString(ftpConnect.Buffer, 0, iBytes);
                    if (iBytes < ftpConnect.Buffer.Length)
                        break;
                }
                ftpConnect.Message = ftpConnect.Message.Replace('\r', ' ');
                char[] seperator = { '\n' };
                string[] strsFileList = ftpConnect.Message.Split(seperator);
                socketData.Close();//數據socket關閉時也會有返回碼
                socketData = null;
                if (ftpConnect.ReplyCode != 226)
                {
                    ftpConnect.ReadReply();
                    if (ftpConnect.ReplyCode != 226)
                        throw new IOException(ftpConnect.ReplyString.Substring(4));
                }
                return strsFileList;
            }
            catch (Exception ex)
            {
                throw (ex);
            }
            finally
            {
                if (socketData != null && socketData.Connected)
                    socketData.Close();
                socketData = null;
                if (ftpConnect != null)
                    ftpConnect.DisConnect();
            }
        }
        //獲取當前目錄下的目錄
        public List<string> ListDirectory(string listUrl)
        {
            List<string> strsFileList = new List<string>();
            List<FileStruct> files = ListDirectoryDetails(listUrl);
            foreach (FileStruct fs in files)
            {
                if (fs.IsDirectory)
                {
                    strsFileList.Add(fs.Name);
                }
            }
            return strsFileList;
        }
        #endregion
        #region 得到詳細的文件列表
        public List<FileStruct> ListDirectoryDetails(string listUrl)
        {
            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            Socket socketData = null;
            try
            {
                ftpUrl = new FTPUrl(listUrl);
                ftpConnect = new FTPConnect(ftpUrl);
                ftpConnect.Connect();
                string strDirPath = ftpUrl.SubUrl;
                if (strDirPath.IndexOf("/") >= 0)
                    strDirPath = strDirPath.Substring(0, strDirPath.LastIndexOf("/"));
                ftpConnect.ChangeDir(strDirPath);
                socketData = ftpConnect.CreateDataSocket();
                ftpConnect.SendCommand("LIST");
                if (ftpConnect.ReplyCode != 150 && ftpConnect.ReplyCode != 125)
                    throw new IOException(ftpConnect.ReplyString.Substring(4));
                //獲得結果
                ftpConnect.Message = "";
                while (true)
                {
                    int iBytes = socketData.Receive(ftpConnect.Buffer, ftpConnect.Buffer.Length, 0);
                    ftpConnect.Message += ftpConnect.EncodeType.GetString(ftpConnect.Buffer, 0, iBytes);
                    if (iBytes < ftpConnect.Buffer.Length)
                        break;
                }
                if (ftpConnect.Message.StartsWith("t"))
                    ftpConnect.Message = ftpConnect.Message.Substring(ftpConnect.Message.IndexOf("\r\n") + 2);
                return this.GetList(ftpConnect.Message);
            }
            catch (Exception ex)
            {
                throw (ex);
            }
            finally
            {
                if (socketData != null && socketData.Connected)
                    socketData.Close();
                socketData = null;
                if (ftpConnect != null)
                    ftpConnect.DisConnect();
            }
        }
        #region 用於得到文件列表的方法
        /// <summary>
        /// 文件列表類型枚舉
        /// </summary>
        private enum FileListStyle
        {
            /// <summary>
            /// Unix系統類型
            /// </summary>
            UnixStyle,
            /// <summary>
            /// Windows系統類型
            /// </summary>
            WindowsStyle,
            /// <summary>
            /// 未知類型
            /// </summary>
            Unknown
        }
        /// <summary>
        /// 列出FTP服務器上面當前目錄的所有文件
        /// </summary>
        /// <param name="listUrl">查看目標目錄</param>
        /// <returns>返回文件信息列表</returns>
        public List<FileStruct> ListFiles(string listUrl)
        {
            List<FileStruct> listFile = null;
            try
            {
                List<FileStruct> listAll = this.ListDirectoryDetails(listUrl);
                listFile = new List<FileStruct>();
                foreach (FileStruct file in listAll)
                {
                    if (!file.IsDirectory)
                    {
                        listFile.Add(file);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return listFile;
        }
        /// <summary>
        /// 列出FTP服務器上面當前目錄的所有的目錄
        /// </summary>
        /// <param name="listUrl">查看目標目錄</param>
        /// <returns>返回目錄信息列表</returns>
        public List<FileStruct> ListDirectories(string listUrl)
        {
            List<FileStruct> listAll = this.ListDirectoryDetails(listUrl);
            List<FileStruct> listDirectory = new List<FileStruct>();
            foreach (FileStruct file in listAll)
            {
                if (file.IsDirectory)
                {
                    listDirectory.Add(file);
                }
            }
            return listDirectory;
        }
        /// <summary>
        /// 獲得文件和目錄列表
        /// </summary>
        /// <param name="datastring">FTP返回的列表字符信息</param>
        private List<FileStruct> GetList(string datastring)
        {
            List<FileStruct> myListArray = new List<FileStruct>();
            string[] dataRecords = datastring.Split('\n');
            FileListStyle _directoryListStyle = GuessFileListStyle(dataRecords);
            foreach (string s in dataRecords)
            {
                if (_directoryListStyle != FileListStyle.Unknown && s != "")
                {
                    FileStruct f = new FileStruct();
                    f.Name = "..";
                    switch (_directoryListStyle)
                    {
                        case FileListStyle.UnixStyle:
                            f = ParseFileStructFromUnixStyleRecord(s);
                            break;
                        case FileListStyle.WindowsStyle:
                            f = ParseFileStructFromWindowsStyleRecord(s);
                            break;
                    }
                    if (!(f.Name == "." || f.Name == ".."))
                    {
                        myListArray.Add(f);
                    }
                }
            }
            return myListArray;
        }

        /// <summary>
        /// 從Windows格式中返回文件信息
        /// </summary>
        /// <param name="Record">文件信息</param>
        private FileStruct ParseFileStructFromWindowsStyleRecord(string Record)
        {
            FileStruct f = new FileStruct();
            string processstr = Record.Trim();
            string dateStr = processstr.Substring(0, 8);
            processstr = (processstr.Substring(8, processstr.Length - 8)).Trim();
            string timeStr = processstr.Substring(0, 7);
            processstr = (processstr.Substring(7, processstr.Length - 7)).Trim();
            DateTimeFormatInfo myDTFI = new CultureInfo("en-US", false).DateTimeFormat;
            myDTFI.ShortTimePattern = "t";
            f.CreateTime = DateTime.Parse(dateStr + " " + timeStr, myDTFI);
            if (processstr.Substring(0, 5) == "<DIR>")
            {
                f.IsDirectory = true;
                processstr = (processstr.Substring(5, processstr.Length - 5)).Trim();
            }
            else
            {
                //string[] strs = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);   // true);
                //processstr = strs[1];
                processstr = processstr.Substring(processstr.IndexOf(' ') + 1);
                f.IsDirectory = false;
            }
            f.Name = processstr;
            return f;
        }
        /// <summary>
        /// 根據文件列表記錄猜想文件列表類型
        /// </summary>
        /// <param name="recordList"></param>
        /// <returns></returns>
        private FileListStyle GuessFileListStyle(string[] recordList)
        {
            foreach (string s in recordList)
            {
                if (s.Length > 10 && Regex.IsMatch(s.Substring(0, 10), "(-|d)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)"))
                {
                    return FileListStyle.UnixStyle;
                }
                else if (s.Length > 8 && Regex.IsMatch(s.Substring(0, 8), "[0-9][0-9]-[0-9][0-9]-[0-9][0-9]"))
                {
                    return FileListStyle.WindowsStyle;
                }
            }
            return FileListStyle.Unknown;
        }
        /// <summary>
        /// 從Unix格式中返回文件信息
        /// </summary>
        /// <param name="Record">文件信息</param>
        private FileStruct ParseFileStructFromUnixStyleRecord(string Record)
        {
            FileStruct f = new FileStruct();
            string processstr = Record.Trim();
            f.Flags = processstr.Substring(0, 10);
            f.IsDirectory = (f.Flags[0] == 'd');
            processstr = (processstr.Substring(11)).Trim();
            _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);   //跳過一部分
            f.Owner = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);
            f.Group = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);
            f.FileSize = Convert.ToInt32(_cutSubstringFromStringWithTrim(ref processstr, ' ', 0));
            //_cutSubstringFromStringWithTrim(ref processstr, ' ', 0);   //跳過一部分
            string yearOrTime = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[2];
            if (yearOrTime.IndexOf(":") >= 0)  //time
            {
                processstr = processstr.Replace(yearOrTime, DateTime.Now.Year.ToString());
            }
            f.CreateTime = DateTime.Parse(_cutSubstringFromStringWithTrim(ref processstr, ' ', 8));
            f.Name = processstr;   //最后就是名稱
            return f;
        }
        /// <summary>
        /// 按照一定的規則進行字符串截取
        /// </summary>
        /// <param name="s">截取的字符串</param>
        /// <param name="c">查找的字符</param>
        /// <param name="startIndex">查找的位置</param>
        private string _cutSubstringFromStringWithTrim(ref string s, char c, int startIndex)
        {
            int pos1 = s.IndexOf(c, startIndex);
            string retString = s.Substring(0, pos1);
            s = (s.Substring(pos1)).Trim();
            return retString;
        }
        #endregion
        #endregion
        #region 上傳文件
        /// <summary>
        /// 直接上傳文件
        /// </summary>
        /// <param name="uploadUrl">上傳的目標全路徑與文件名</param>
        /// <param name="isContinueUpload">是否斷點續傳</param>
        /// <returns>上傳是否成功</returns>
        public bool UploadFileNow(byte[] fileBytes, string uploadUrl, bool isContinueUpload)
        {
            bool result = true;

            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            Socket socketData = null;
            int iCharIndex = 0;
            int bytesRead;
            long lOffset = 0, lTotalReaded = 0;
            string strDirUrl, strDirUrlTemp;
            try
            {
                ftpUrl = new FTPUrl(uploadUrl);
                ftpConnect = new FTPConnect(ftpUrl);
                ftpConnect.Connect();
                this.m_FTPConnectList.Add(ftpConnect);//添加到控制器中
                #region 判斷並創建文件夾
                strDirUrl = ftpUrl.SubUrl;
                if (strDirUrl.IndexOf("/") >= 0)
                    strDirUrl = strDirUrl.Substring(0, strDirUrl.LastIndexOf("/"));
                while (true && strDirUrl.Trim() != "")
                {
                    iCharIndex = strDirUrl.IndexOf("/", iCharIndex) + 1;
                    if (iCharIndex == 0)
                        strDirUrlTemp = strDirUrl;
                    else
                        strDirUrlTemp = strDirUrl.Substring(0, iCharIndex);
                    if (strDirUrlTemp == "")
                        continue;
                    ftpConnect.SendCommand("MKD " + strDirUrlTemp);
                    if (ftpConnect.ReplyCode != 257 && ftpConnect.ReplyCode != 550)
                        throw new IOException(ftpConnect.ReplyString.Substring(4));
                    if (strDirUrlTemp == strDirUrl)
                        break;
                }
                #endregion
                ftpConnect.ChangeDir(strDirUrl);
                #region 得到服務器上的文件大小
                if (isContinueUpload)
                {
                    string strDirName = ftpUrl.SubUrl;
                    if (strDirName.IndexOf("/") >= 0)
                        strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/"));
                    ftpConnect.ChangeDir(strDirName);
                    ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl));
                    if (ftpConnect.ReplyCode == 213)
                        lOffset = Int64.Parse(ftpConnect.ReplyString.Substring(4));
                }
                #endregion
                #region 開始上傳
                lTotalReaded = lOffset;
                socketData = ftpConnect.CreateDataSocket();
                if (lOffset > 0)
                    ftpConnect.SendCommand("APPE " + Path.GetFileName(uploadUrl));
                else
                    ftpConnect.SendCommand("STOR " + Path.GetFileName(uploadUrl));
                if (!(ftpConnect.ReplyCode == 125 || ftpConnect.ReplyCode == 150))
                    throw new IOException(ftpConnect.ReplyString.Substring(4));
                ftpConnect.DataTransmitting = true;
                while (true)
                {
                    if (!ftpConnect.DataTransmitting)
                    {
                        this.OnFileUploadCanceled(ftpConnect);
                        break;
                    }
                    this.OnFileUploading(ftpConnect, fileBytes.Length, lTotalReaded);
                    //開始上傳資料
                    bytesRead = (int)((fileBytes.Length > lTotalReaded + ftpConnect.Buffer.Length) ? ftpConnect.Buffer.Length : (fileBytes.Length - lTotalReaded));
                    if (bytesRead == 0)
                        break;
                    Array.Copy(fileBytes, lTotalReaded, ftpConnect.Buffer, 0, bytesRead);
                    socketData.Send(ftpConnect.Buffer, bytesRead, 0);
                    lTotalReaded += bytesRead;
                }
                if (socketData.Connected)
                    socketData.Close();
                if (ftpConnect.DataTransmitting)
                {
                    if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                    {
                        ftpConnect.ReadReply();
                        if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                            throw new IOException(ftpConnect.ReplyString.Substring(4));
                    }
                    this.OnFileUploadCompleted(ftpConnect);
                }
                #endregion
            }
            catch (Exception ex)
            {
                result = false;
                throw (ex);
            }
            finally
            {
                if (socketData != null && socketData.Connected)
                    socketData.Close();
                if (ftpConnect != null)
                {
                    ftpConnect.DisConnect();
                    this.m_FTPConnectList.Remove(ftpConnect);
                }
            }
            return result;
        }
        /// <summary>
        /// 直接上傳文件
        /// </summary>
        /// <param name="filePath">上傳文件的全路徑</param>
        /// <param name="uploadUrl">上傳的目標全路徑與文件名</param>
        /// <param name="isContinueUpload">是否斷點續傳</param>
        /// <returns>上傳是否成功</returns>
        public bool UploadFileNow(string filePath, string uploadUrl, bool isContinueUpload)
        {
            bool result = true;

            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            Socket socketData = null;
            FileStream fileStream = null;
            int iCharIndex = 0;
            int bytesRead;
            long lOffset = 0, lTotalReaded = 0;
            string strDirUrl, strDirUrlTemp;
            try
            {
                ftpUrl = new FTPUrl(uploadUrl);
                ftpConnect = new FTPConnect(ftpUrl);
                ftpConnect.Connect();
                this.m_FTPConnectList.Add(ftpConnect);//添加到控制器中
                #region 判斷並創建文件夾
                strDirUrl = ftpUrl.SubUrl;
                if (strDirUrl.IndexOf("/") >= 0)
                    strDirUrl = strDirUrl.Substring(0, strDirUrl.LastIndexOf("/"));
                while (true && strDirUrl.Trim() != "")
                {
                    iCharIndex = strDirUrl.IndexOf("/", iCharIndex) + 1;
                    if (iCharIndex == 0)
                        strDirUrlTemp = strDirUrl;
                    else
                        strDirUrlTemp = strDirUrl.Substring(0, iCharIndex);
                    if (strDirUrlTemp == "")
                        continue;
                    ftpConnect.SendCommand("MKD " + strDirUrlTemp);
                    if (ftpConnect.ReplyCode != 257 && ftpConnect.ReplyCode != 550)
                        throw new IOException(ftpConnect.ReplyString.Substring(4));
                    if (strDirUrlTemp == strDirUrl)
                        break;
                }
                #endregion
                ftpConnect.ChangeDir(strDirUrl);
                #region 得到服務器上的文件大小
                if (isContinueUpload)
                {
                    string strDirName = ftpUrl.SubUrl;
                    if (strDirName.IndexOf("/") >= 0)
                        strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/"));
                    ftpConnect.ChangeDir(strDirName);
                    ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl));
                    if (ftpConnect.ReplyCode == 213)
                        lOffset = Int64.Parse(ftpConnect.ReplyString.Substring(4));
                }
                #endregion
                #region 開始上傳
                fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                lTotalReaded = lOffset;
                fileStream.Seek(lOffset, SeekOrigin.Begin);
                socketData = ftpConnect.CreateDataSocket();
                if (lOffset > 0)
                    ftpConnect.SendCommand("APPE " + Path.GetFileName(filePath));
                else
                    ftpConnect.SendCommand("STOR " + Path.GetFileName(filePath));
                if (!(ftpConnect.ReplyCode == 125 || ftpConnect.ReplyCode == 150))
                    throw new IOException(ftpConnect.ReplyString.Substring(4));
                ftpConnect.DataTransmitting = true;
                while (true)
                {
                    if (!ftpConnect.DataTransmitting)
                    {
                        this.OnFileUploadCanceled(ftpConnect);
                        break;
                    }
                    this.OnFileUploading(ftpConnect, fileStream.Length, lTotalReaded);
                    //開始上傳資料
                    bytesRead = fileStream.Read(ftpConnect.Buffer, 0, ftpConnect.Buffer.Length);
                    if (bytesRead == 0)
                        break;
                    socketData.Send(ftpConnect.Buffer, bytesRead, 0);
                    lTotalReaded += bytesRead;
                }
                fileStream.Close();
                if (socketData.Connected)
                    socketData.Close();
                if (ftpConnect.DataTransmitting)
                {
                    if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                    {
                        ftpConnect.ReadReply();
                        if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                            throw new IOException(ftpConnect.ReplyString.Substring(4));
                    }
                    this.OnFileUploadCompleted(ftpConnect);
                }
                #endregion
            }
            catch (Exception ex)
            {
                result = false;
                throw (ex);
            }
            finally
            {
                if (fileStream != null)
                    fileStream.Close();
                if (socketData != null && socketData.Connected)
                    socketData.Close();
                if (ftpConnect != null)
                {
                    ftpConnect.DisConnect();
                    this.m_FTPConnectList.Remove(ftpConnect);
                }     
            }
            return result;
        }
        /// <summary>
        /// 上傳文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="uploadUrl"></param>
        public string UploadFile(string filePath, string uploadUrl)
        {
            return this.UploadFile(filePath, uploadUrl, false);
        }
        /// <summary>
        /// 上傳文件
        /// </summary>
        /// <param name="filePath">上傳文件的全路徑</param>
        /// <param name="uploadUrl">上傳的目標全路徑 包含了用戶名用戶密碼與文件名</param>
        /// <param name="isContinueUpload">是否斷點續傳</param>
        /// <returns>返回控制上傳下載的ID</returns>
        public string UploadFile(string filePath, string uploadUrl, bool isContinueUpload)
        {
            String strFTPId = System.Guid.NewGuid().ToString();
            IList<object> objList = new List<object> { filePath, uploadUrl, isContinueUpload, strFTPId };
            System.Threading.Thread threadUpload = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(ThreadUploadFile));
            threadUpload.Start(objList);  //開始采用線程方式下載
            return strFTPId;
        }
        /// <summary>
        /// 線程接收上傳
        /// </summary>
        /// <param name="obj"></param>
        private void ThreadUploadFile(object obj)
        {
            string filePath;
            string uploadUrl;
            bool isContinueUpload;
            string strFTPId;
            IList<object> objList = obj as IList<object>;
            if (objList != null && objList.Count == 4)
            {
                filePath = objList[0] as string;
                uploadUrl = objList[1] as string;
                isContinueUpload = (bool)objList[2];
                strFTPId = objList[3] as string;
                this.ThreadUploadFile(filePath, uploadUrl, isContinueUpload, strFTPId);
            }
        }
        /// <summary>
        /// 線程上傳文件
        /// </summary>
        /// <param name="filePath">上傳文件的全路徑</param>
        /// <param name="uploadUrl">上傳的目標全路徑與文件名</param>
        /// <param name="isContinueUpload">是否斷點續傳</param>
        /// <returns>上傳是否成功</returns>
        private bool ThreadUploadFile(string filePath, string uploadUrl, bool isContinueUpload, string strFTPId)
        {
            bool result = true;

            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            Socket socketData = null;
            FileStream fileStream = null;
            int iCharIndex = 0;
            int bytesRead;
            long lOffset = 0, lTotalReaded = 0;
            string strDirUrl, strDirUrlTemp;
            try
            {
                ftpUrl = new FTPUrl(uploadUrl);
                ftpConnect = new FTPConnect(ftpUrl, strFTPId);
                ftpConnect.Connect();
                this.m_FTPConnectList.Add(ftpConnect);//添加到控制器中
                #region 判斷並創建文件夾
                strDirUrl = ftpUrl.SubUrl;
                if (strDirUrl.IndexOf("/") >= 0)
                    strDirUrl = strDirUrl.Substring(0, strDirUrl.LastIndexOf("/"));
                while (true && strDirUrl.Trim() != "")
                {
                    iCharIndex = strDirUrl.IndexOf("/", iCharIndex) + 1;
                    if (iCharIndex == 0)
                        strDirUrlTemp = strDirUrl;
                    else
                        strDirUrlTemp = strDirUrl.Substring(0, iCharIndex);
                    if (strDirUrlTemp == "")
                        continue;
                    ftpConnect.SendCommand("MKD " + strDirUrlTemp);
                    if (ftpConnect.ReplyCode != 257 && ftpConnect.ReplyCode != 550)
                        throw new IOException(ftpConnect.ReplyString.Substring(4));
                    if (strDirUrlTemp == strDirUrl)
                        break;
                }
                #endregion
                ftpConnect.ChangeDir(strDirUrl);
                #region 得到服務器上的文件大小
                if (isContinueUpload)
                {
                    string strDirName = ftpUrl.SubUrl;
                    if (strDirName.IndexOf("/") >= 0)
                        strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/"));
                    ftpConnect.ChangeDir(strDirName);
                    ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl));
                    if (ftpConnect.ReplyCode == 213)
                        lOffset = Int64.Parse(ftpConnect.ReplyString.Substring(4));
                }
                #endregion
                #region 開始上傳
                fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                lTotalReaded = lOffset;
                fileStream.Seek(lOffset, SeekOrigin.Begin);
                socketData = ftpConnect.CreateDataSocket();
                if (lOffset > 0)
                    ftpConnect.SendCommand("APPE " + Path.GetFileName(uploadUrl));
                else
                    ftpConnect.SendCommand("STOR " + Path.GetFileName(uploadUrl));
                if (!(ftpConnect.ReplyCode == 125 || ftpConnect.ReplyCode == 150))
                    throw new IOException(ftpConnect.ReplyString.Substring(4));
                ftpConnect.DataTransmitting = true;
                while (true)
                {
                    if (!ftpConnect.DataTransmitting)
                    {
                        this.OnFileUploadCanceled(ftpConnect);
                        break;
                    }
                    this.OnFileUploading(ftpConnect, fileStream.Length, lTotalReaded);
                    //開始上傳資料
                    bytesRead = fileStream.Read(ftpConnect.Buffer, 0, ftpConnect.Buffer.Length);
                    if (bytesRead == 0)
                        break;
                    socketData.Send(ftpConnect.Buffer, bytesRead, 0);
                    lTotalReaded += bytesRead;
                }
                fileStream.Close();
                if (socketData.Connected)
                    socketData.Close();
                if (ftpConnect.DataTransmitting)
                {
                    if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                    {
                        ftpConnect.ReadReply();
                        if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                            throw new IOException(ftpConnect.ReplyString.Substring(4));
                    }
                    this.OnFileUploadCompleted(ftpConnect);
                }
                #endregion
            }
            catch (Exception ex)
            {
                result = false;
                this.OnFtpError(ftpConnect, ex);
            }
            finally
            {
                if (fileStream != null)
                    fileStream.Close();
                if (socketData != null && socketData.Connected)
                    socketData.Close();
                if (ftpConnect != null)
                {
                    ftpConnect.DisConnect();
                    this.m_FTPConnectList.Remove(ftpConnect);
                } 
            }
            return result;
        }
        /// <summary>
        /// 取消正在上傳的文件
        /// </summary>
        /// <returns></returns>
        public void CancelUploadFile(FTPConnect ftpConnect)
        {
            if (ftpConnect != null)
                ftpConnect.DataTransmitting = false;
        }
        /// <summary>
        /// 取消正在上傳的文件
        /// </summary>
        /// <param name="strID"></param>
        public void CancelUploadFile(string strID)
        {
            foreach (FTPConnect ftp in this.m_FTPConnectList)
            {
                if (ftp != null && ftp.ID == strID)
                {
                    ftp.DataTransmitting = false;
                    break;
                }
            }
        }
        #endregion
        #region 下載文件
        /// <summary>
        /// 直接下載文件
        /// </summary>
        /// <param name="downloadUrl">要下載文件的路徑</param>
        /// <param name="fileBytes">存貯的內容</param>
        /// <returns>下載是否成功</returns>
        public bool DownloadFileNow(string downloadUrl, out byte[] fileBytes)
        {
            bool result = true;

            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            Socket socketData = null;
            fileBytes = new byte[] { };
            int bytesRead;
            long lTotalReaded = 0, lFileSize;
            try
            {
                ftpUrl = new FTPUrl(downloadUrl);
                ftpConnect = new FTPConnect(ftpUrl);
                ftpConnect.Connect();
                this.m_FTPConnectList.Add(ftpConnect);//添加到控制器中
                string strDirUrl = ftpUrl.SubUrl;
                if (strDirUrl.IndexOf("/") >= 0)
                    strDirUrl = strDirUrl.Substring(0, strDirUrl.LastIndexOf("/"));
                ftpConnect.ChangeDir(strDirUrl);
                #region 得到服務器上的文件大小
                string strDirName = ftpUrl.SubUrl;
                if (strDirName.IndexOf("/") >= 0)
                    strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/"));
                ftpConnect.ChangeDir(strDirName);
                ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl));
                if (ftpConnect.ReplyCode == 213)
                    lFileSize = Int64.Parse(ftpConnect.ReplyString.Substring(4));
                else
                    throw new IOException(ftpConnect.ReplyString.Substring(4));
                #endregion

                socketData = ftpConnect.CreateDataSocket();
                fileBytes = new byte[lFileSize];
                ftpConnect.SendCommand("RETR " + Path.GetFileName(ftpUrl.SubUrl));
                if (!(ftpConnect.ReplyCode == 150 || ftpConnect.ReplyCode == 125 || ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                    throw new IOException(ftpConnect.ReplyString.Substring(4));
                #region 開始下載
                ftpConnect.DataTransmitting = true;
                while (true)
                {
                    if (!ftpConnect.DataTransmitting)    //判斷取消是否取消了下載
                    {
                        this.OnFileDownloadCanceled(ftpConnect);
                        break;
                    }
                    this.OnFileDownloading(ftpConnect, lFileSize, lTotalReaded);
                    //開始將文件流寫入本地
                    bytesRead = socketData.Receive(ftpConnect.Buffer, ftpConnect.Buffer.Length, 0);
                    if (bytesRead <= 0)
                        break;
                    Array.Copy(ftpConnect.Buffer, 0, fileBytes, lTotalReaded, bytesRead);
                    lTotalReaded += bytesRead;
                }
                if (socketData.Connected)
                    socketData.Close();
                if (ftpConnect.DataTransmitting)
                {
                    if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                    {
                        ftpConnect.ReadReply();
                        if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                            throw new IOException(ftpConnect.ReplyString.Substring(4));
                    }
                    this.OnFileDownloadCompleted(ftpConnect);
                }
                #endregion
            }
            catch (Exception ex)
            {
                result = false;
                throw (ex);
            }
            finally
            {
                if (socketData != null && socketData.Connected)
                    socketData.Close();
                if (ftpConnect != null)
                {
                    ftpConnect.DisConnect();
                    this.m_FTPConnectList.Remove(ftpConnect);
                } 
            }
            return result;
        }
        /// <summary>
        /// 直接下載文件
        /// </summary>
        /// <param name="downloadUrl">要下載文件的路徑</param>
        /// <param name="targetFile">目標存在全路徑</param>
        /// <param name="isContinueDownload">是否斷點續傳</param>
        /// <returns>下載是否成功</returns>
        public bool DownloadFileNow(string downloadUrl, string targetFile, bool isContinueDownload)
        {
            bool result = true;

            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            Socket socketData = null;
            FileStream fileStream = null;
            int bytesRead;
            long lTotalReaded = 0, lFileSize;
            try
            {
                ftpUrl = new FTPUrl(downloadUrl);
                ftpConnect = new FTPConnect(ftpUrl);
                ftpConnect.Connect();
                this.m_FTPConnectList.Add(ftpConnect);//添加到控制器中
                string strDirUrl = ftpUrl.SubUrl;
                if (strDirUrl.IndexOf("/") >= 0)
                    strDirUrl = strDirUrl.Substring(0, strDirUrl.LastIndexOf("/"));
                ftpConnect.ChangeDir(strDirUrl);
                #region 得到服務器上的文件大小
                string strDirName = ftpUrl.SubUrl;
                if (strDirName.IndexOf("/") >= 0)
                    strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/"));
                ftpConnect.ChangeDir(strDirName);
                ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl));
                if (ftpConnect.ReplyCode == 213)
                    lFileSize = Int64.Parse(ftpConnect.ReplyString.Substring(4));
                else
                    throw new IOException(ftpConnect.ReplyString.Substring(4));
                #endregion

                socketData = ftpConnect.CreateDataSocket();
                //斷點續傳長度的偏移量
                if (System.IO.File.Exists(targetFile) && isContinueDownload)
                {
                    System.IO.FileInfo fiInfo = new FileInfo(targetFile);
                    lTotalReaded = fiInfo.Length;
                    ftpConnect.SendCommand("REST " + fiInfo.Length.ToString());
                    if (ftpConnect.ReplyCode != 350)
                        throw new IOException(ftpConnect.ReplyString.Substring(4));
                }
                ftpConnect.SendCommand("RETR " + Path.GetFileName(ftpUrl.SubUrl));
                if (!(ftpConnect.ReplyCode == 150 || ftpConnect.ReplyCode == 125 || ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                    throw new IOException(ftpConnect.ReplyString.Substring(4));
                #region 開始下載
                string strTargetPath = targetFile;
                strTargetPath = strTargetPath.Substring(0, strTargetPath.LastIndexOf("\\"));//這里本來是//
                if (!System.IO.Directory.Exists(strTargetPath)) //判斷目標路徑是否存在,如果不存在就創建
                    System.IO.Directory.CreateDirectory(strTargetPath);
                if (System.IO.File.Exists(targetFile) && isContinueDownload)  //目標文件已經是全路徑了 斷點續傳
                    fileStream = new System.IO.FileStream(targetFile, System.IO.FileMode.Append, System.IO.FileAccess.Write);
                else
                    fileStream = new System.IO.FileStream(targetFile, System.IO.FileMode.Create, System.IO.FileAccess.Write);
                ftpConnect.DataTransmitting = true;
                while (true)
                {
                    if (!ftpConnect.DataTransmitting)    //判斷取消是否取消了下載
                    {
                        this.OnFileDownloadCanceled(ftpConnect);
                        break;
                    }
                    this.OnFileDownloading(ftpConnect, lFileSize, lTotalReaded);
                    //開始將文件流寫入本地
                    bytesRead = socketData.Receive(ftpConnect.Buffer, ftpConnect.Buffer.Length, 0);
                    if (bytesRead <= 0)
                        break;
                    fileStream.Write(ftpConnect.Buffer, 0, bytesRead);
                    lTotalReaded += bytesRead;
                }
                fileStream.Close();
                if (socketData.Connected)
                    socketData.Close();
                if (ftpConnect.DataTransmitting)
                {
                    if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                    {
                        ftpConnect.ReadReply();
                        if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                            throw new IOException(ftpConnect.ReplyString.Substring(4));
                    }
                    this.OnFileDownloadCompleted(ftpConnect);
                }
                #endregion
            }
            catch (Exception ex)
            {
                result = false;
                throw (ex);
            }
            finally
            {
                if (fileStream != null)
                    fileStream.Close();
                if (socketData != null && socketData.Connected)
                    socketData.Close();
                if (ftpConnect != null)
                {
                    ftpConnect.DisConnect();
                    this.m_FTPConnectList.Remove(ftpConnect);
                }
            }
            return result;
        }
        /// <summary>
        /// 下載文件
        /// </summary>
        /// <param name="downloadUrl"></param>
        /// <param name="targetFile"></param>
        public string DownloadFile(string downloadUrl, string targetFile)
        {
            return this.DownloadFile(downloadUrl, targetFile, false);
        }
        /// <summary>
        /// 下載文件
        /// </summary>
        /// <param name="downloadUrl">要下載文件的路徑 包含了登錄名與登錄密碼</param>
        /// <param name="TargetFile">目標存在路徑包含文件名</param>
        /// <param name="isContinueDownload">是否斷點續傳</param>
        /// <returns>返回下載控制ID</returns>
        public string DownloadFile(string downloadUrl, string targetFile, bool isContinueDownload)
        {
            String strFTPId = System.Guid.NewGuid().ToString();
            IList<object> objList = new List<object> { downloadUrl, targetFile, isContinueDownload, strFTPId };
            System.Threading.Thread threadDownload = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(ThreadDownloadFile));
            threadDownload.Start(objList);  //開始采用線程方式下載
            return strFTPId;
        }
        /// <summary>
        /// 線程接收下載
        /// </summary>
        /// <param name="obj"></param>
        private void ThreadDownloadFile(object obj)
        {
            string downloadUrl;
            string targetFile;
            bool isContinueDownload;
            string strFTPId;
            IList<object> objList = obj as IList<object>;
            if (objList != null && objList.Count == 4)
            {
                downloadUrl = objList[0] as string;
                targetFile = objList[1] as string;
                isContinueDownload = (bool)objList[2];
                strFTPId = objList[3] as String;
                this.ThreadDownloadFile(downloadUrl, targetFile, isContinueDownload, strFTPId);
            }
        }
        /// <summary>
        /// 線程下載文件
        /// </summary>
        /// <param name="downloadUrl">要下載文件的路徑</param>
        /// <param name="targetFile">目標存在全路徑</param>
        /// <param name="isContinueDownload">是否斷點續傳</param>
        /// <returns>下載是否成功</returns>
        private bool ThreadDownloadFile(string downloadUrl, string targetFile, bool isContinueDownload, string strFTPId)
        {
            bool result = true;

            FTPUrl ftpUrl = null;
            FTPConnect ftpConnect = null;
            Socket socketData = null;
            FileStream fileStream = null;
            int bytesRead;
            long lTotalReaded = 0, lFileSize;
            try
            {
                ftpUrl = new FTPUrl(downloadUrl);
                ftpConnect = new FTPConnect(ftpUrl, strFTPId);
                ftpConnect.Connect();
                this.m_FTPConnectList.Add(ftpConnect);//添加到控制器中
                string strDirUrl = ftpUrl.SubUrl;
                if (strDirUrl.IndexOf("/") >= 0)
                    strDirUrl = strDirUrl.Substring(0, strDirUrl.LastIndexOf("/"));
                ftpConnect.ChangeDir(strDirUrl);
                #region 得到服務器上的文件大小
                string strDirName = ftpUrl.SubUrl;
                if (strDirName.IndexOf("/") >= 0)
                    strDirName = strDirName.Substring(0, strDirName.LastIndexOf("/"));
                ftpConnect.ChangeDir(strDirName);
                ftpConnect.SendCommand("SIZE " + Path.GetFileName(ftpUrl.SubUrl));
                if (ftpConnect.ReplyCode == 213)
                    lFileSize = Int64.Parse(ftpConnect.ReplyString.Substring(4));
                else
                    throw new IOException(ftpConnect.ReplyString.Substring(4));
                #endregion

                socketData = ftpConnect.CreateDataSocket();
                //斷點續傳長度的偏移量
                if (System.IO.File.Exists(targetFile) && isContinueDownload)
                {
                    System.IO.FileInfo fiInfo = new FileInfo(targetFile);
                    lTotalReaded = fiInfo.Length;
                    ftpConnect.SendCommand("REST " + fiInfo.Length.ToString());
                    if (ftpConnect.ReplyCode != 350)
                        throw new IOException(ftpConnect.ReplyString.Substring(4));
                }
                ftpConnect.SendCommand("RETR " + Path.GetFileName(ftpUrl.SubUrl));
                if (!(ftpConnect.ReplyCode == 150 || ftpConnect.ReplyCode == 125 || ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                    throw new IOException(ftpConnect.ReplyString.Substring(4));
                #region 開始下載
                string strTargetPath = targetFile;
                strTargetPath = strTargetPath.Substring(0, strTargetPath.LastIndexOf("//"));
                if (!System.IO.Directory.Exists(strTargetPath)) //判斷目標路徑是否存在,如果不存在就創建
                    System.IO.Directory.CreateDirectory(strTargetPath);
                if (System.IO.File.Exists(targetFile) && isContinueDownload)  //目標文件已經是全路徑了 斷點續傳
                    fileStream = new System.IO.FileStream(targetFile, System.IO.FileMode.Append, System.IO.FileAccess.Write);
                else
                    fileStream = new System.IO.FileStream(targetFile, System.IO.FileMode.Create, System.IO.FileAccess.Write);
                ftpConnect.DataTransmitting = true;
                while (true)
                {
                    if (!ftpConnect.DataTransmitting)    //判斷取消是否取消了下載
                    {
                        this.OnFileDownloadCanceled(ftpConnect);
                        break;
                    }
                    this.OnFileDownloading(ftpConnect, lFileSize, lTotalReaded);
                    //開始將文件流寫入本地
                    bytesRead = socketData.Receive(ftpConnect.Buffer, ftpConnect.Buffer.Length, 0);
                    if (bytesRead <= 0)
                        break;
                    fileStream.Write(ftpConnect.Buffer, 0, bytesRead);
                    lTotalReaded += bytesRead;
                }
                fileStream.Close();
                if (socketData.Connected)
                    socketData.Close();
                if (ftpConnect.DataTransmitting)
                {
                    if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                    {
                        ftpConnect.ReadReply();
                        if (!(ftpConnect.ReplyCode == 226 || ftpConnect.ReplyCode == 250))
                            throw new IOException(ftpConnect.ReplyString.Substring(4));
                    }
                    this.OnFileDownloadCompleted(ftpConnect);
                }
                #endregion
            }
            catch (Exception ex)
            {
                result = false;
                this.OnFtpError(ftpConnect, ex);
            }
            finally
            {
                if (fileStream != null)
                    fileStream.Close();
                if (socketData != null && socketData.Connected)
                    socketData.Close();
                if (ftpConnect != null)
                {
                    ftpConnect.DisConnect();
                    this.m_FTPConnectList.Remove(ftpConnect);
                }
            }
            return result;
        }
        /// <summary>
        /// 取消正在下載的文件
        /// </summary>
        /// <returns></returns>
        public void CancelDownloadFile(FTPConnect ftpConnect)
        {
            if (ftpConnect != null)
                ftpConnect.DataTransmitting = false;
        }
        /// <summary>
        /// 取消正在下載的文件
        /// </summary>
        /// <param name="strID"></param>
        public void CancelDownloadFile(string strID)
        {
            foreach (FTPConnect ftp in this.m_FTPConnectList)
            {
                if (ftp != null && ftp.ID == strID)
                {
                    ftp.DataTransmitting = false;
                    break;
                }
            }
        }
        #endregion
        #region 根據指定的ID查找FTPConnect
        /// <summary>
        /// 根據指定的ID查找FTPConnect
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public FTPConnect FindFTPConnectByID(string id)
        {
            foreach (FTPConnect ftpConnect in this.m_FTPConnectList)
            {
                if (ftpConnect != null && ftpConnect.ID == id)
                    return ftpConnect;
            }
            return null;
        }
        #endregion

        #region 傳輸類型
        public enum FTPType
        {
            /// <summary>
            /// 無狀態
            /// </summary>
            None,
            /// <summary>
            /// 上傳
            /// </summary>
            Upload,
            /// <summary>
            /// 下載
            /// </summary>
            Download
        }
        #endregion
    }
    #region 文件信息結構
    public struct FileStruct
    {
        public string Flags;
        public string Owner;
        public string Group;
        public int FileSize;
        public bool IsDirectory;
        public DateTime CreateTime;
        public string Name;
    }
    #endregion
    #region 文件傳輸進度控制事件
    public delegate void FTPSendEventHandler(object sender, FTPSendEventArgs e);
    public class FTPSendEventArgs : System.EventArgs
    {
        private long m_totalbytes;			// Total Bytes
        private long m_bytestransfered;

        public FTPSendEventArgs()
        {
            m_totalbytes = 0;
            m_bytestransfered = 0;
        }
        public FTPSendEventArgs(long lTotalBytes, long lBytesTransfered)
        {
            m_totalbytes = lTotalBytes;
            m_bytestransfered = lBytesTransfered;
        }
        /// <summary>
        /// 總字節數
        /// </summary>
        public long TotalBytes
        {
            get { return m_totalbytes; }
            set { m_totalbytes = value; }
        }
        /// <summary>
        /// 已傳輸字節數
        /// </summary>
        public long BytesTransfered
        {
            get { return m_bytestransfered; }
            set { m_bytestransfered = value; }
        }
    }
    public delegate void FTPErrorEventHandler(object sender, FTPErrorEventArgs e);
    public class FTPErrorEventArgs : System.EventArgs
    {
        private Exception m_Error = null;
        public FTPErrorEventArgs() { }
        public FTPErrorEventArgs(Exception error)
        {
            this.m_Error = error;
        }
        /// <summary>
        /// 錯誤消息
        /// </summary>
        public Exception Error
        {
            get { return this.m_Error; }
            set { this.m_Error = value; }
        }
    }
    #endregion
}

 使用示例:

private void Download()
        {
            FTPHelper ftphelper = new FTPHelper();
            ftphelper.FileDownloading += new FTPSendEventHandler(ftphelper_FileDownloading);
            ftphelper.FileDownloadCompleted += new EventHandler(ftphelper_FileDownloadCompleted);
            ftphelper.DownloadFileNow("ftp://userName:password@address/test.mp3", "D://office//test.mp3", false);
        }
private void ftphelper_FileDownloadCompleted(object sender, EventArgs e)
        {
            MessageBox.Show("下載完成");
        }

private void ftphelper_FileDownloading(object sender, FTPSendEventArgs e)
        {
            progressBar.Maximum = (int)e.TotalBytes;
            progressBar.Value = ((int)e.BytesTransfered);
        }

 使用WebRequest的另一個Ftp類:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Globalization;
using System.Text.RegularExpressions;

namespace Ftp
{
    #region 文件信息結構
    public struct FileStruct
    {
        public string Flags;
        public string Owner;
        public string Group;
        public bool IsDirectory;
        public DateTime CreateTime;
        public string Name;
    }
    public enum FileListStyle
    {
        UnixStyle,
        WindowsStyle,
        Unknown
    }
    #endregion


    /// <summary>
    /// FTP處理操作類
    /// 功能:
    /// 下載文件
    /// 上傳文件
    /// 上傳文件的進度信息
    /// 下載文件的進度信息
    /// 刪除文件
    /// 列出文件
    /// 列出目錄
    /// 進入子目錄
    /// 退出當前目錄返回上一層目錄
    /// 判斷遠程文件是否存在
    /// 判斷遠程文件是否存在
    /// 刪除遠程文件    
    /// 建立目錄
    /// 刪除目錄
    /// 文件(目錄)改名
    /// </summary>
    public class FTPHelper
    {
        #region 屬性信息
        /// <summary>
        /// FTP請求對象
        /// </summary>
        FtpWebRequest Request = null;
        /// <summary>
        /// FTP響應對象
        /// </summary>
        FtpWebResponse Response = null;
        /// <summary>
        /// FTP服務器地址
        /// </summary>
        private Uri _Uri;
        /// <summary>
        /// FTP服務器地址
        /// </summary>
        public Uri Uri
        {
            get
            {
                if (_DirectoryPath == "/")
                {
                    return _Uri;
                }
                else
                {
                    string strUri = _Uri.ToString();
                    if (strUri.EndsWith("/"))
                    {
                        strUri = strUri.Substring(0, strUri.Length - 1);
                    }
                    return new Uri(strUri + this.DirectoryPath);
                }
            }
            set
            {
                if (value.Scheme != Uri.UriSchemeFtp)
                {
                    throw new Exception("Ftp 地址格式錯誤!");
                }
                _Uri = new Uri(value.GetLeftPart(UriPartial.Authority));
                _DirectoryPath = value.AbsolutePath;
                if (!_DirectoryPath.EndsWith("/"))
                {
                    _DirectoryPath += "/";
                }
            }
        }

        /// <summary>
        /// 當前工作目錄
        /// </summary>
        private string _DirectoryPath;

        /// <summary>
        /// 當前工作目錄
        /// </summary>
        public string DirectoryPath
        {
            get { return _DirectoryPath; }
            set { _DirectoryPath = value; }
        }

        /// <summary>
        /// FTP登錄用戶
        /// </summary>
        private string _UserName;
        /// <summary>
        /// FTP登錄用戶
        /// </summary>
        public string UserName
        {
            get { return _UserName; }
            set { _UserName = value; }
        }

        /// <summary>
        /// 錯誤信息
        /// </summary>
        private string _ErrorMsg;
        /// <summary>
        /// 錯誤信息
        /// </summary>
        public string ErrorMsg
        {
            get { return _ErrorMsg; }
            set { _ErrorMsg = value; }
        }

        /// <summary>
        /// FTP登錄密碼
        /// </summary>
        private string _Password;
        /// <summary>
        /// FTP登錄密碼
        /// </summary>
        public string Password
        {
            get { return _Password; }
            set { _Password = value; }
        }

        /// <summary>
        /// 連接FTP服務器的代理服務
        /// </summary>
        private WebProxy _Proxy = null;
        /// <summary>
        /// 連接FTP服務器的代理服務
        /// </summary>
        public WebProxy Proxy
        {
            get
            {
                return _Proxy;
            }
            set
            {
                _Proxy = value;
            }
        }

        /// <summary>
        /// 是否需要刪除臨時文件
        /// </summary>
        private bool _isDeleteTempFile = false;
        /// <summary>
        /// 異步上傳所臨時生成的文件
        /// </summary>
        private string _UploadTempFile = "";
        #endregion


        #region 事件
        public delegate void De_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e);
        public delegate void De_DownloadDataCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e);
        public delegate void De_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e);
        public delegate void De_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e);

        /// <summary>
        /// 異步下載進度發生改變觸發的事件
        /// </summary>
        public event De_DownloadProgressChanged DownloadProgressChanged;
        /// <summary>
        /// 異步下載文件完成之后觸發的事件
        /// </summary>
        public event De_DownloadDataCompleted DownloadDataCompleted;
        /// <summary>
        /// 異步上傳進度發生改變觸發的事件
        /// </summary>
        public event De_UploadProgressChanged UploadProgressChanged;
        /// <summary>
        /// 異步上傳文件完成之后觸發的事件
        /// </summary>
        public event De_UploadFileCompleted UploadFileCompleted;
        #endregion


        #region 構造析構函數
        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="FtpUri">FTP地址</param>
        /// <param name="strUserName">登錄用戶名</param>
        /// <param name="strPassword">登錄密碼</param>
        public FTPHelper(Uri FtpUri, string strUserName, string strPassword)
        {
            this._Uri = new Uri(FtpUri.GetLeftPart(UriPartial.Authority));
            _DirectoryPath = FtpUri.AbsolutePath;
            if (!_DirectoryPath.EndsWith("/"))
            {
                _DirectoryPath += "/";
            }
            this._UserName = strUserName;
            this._Password = strPassword;
            this._Proxy = null;
        }
        /// <summary>
        /// 構造函數
        /// </summary>
        /// <param name="FtpUri">FTP地址</param>
        /// <param name="strUserName">登錄用戶名</param>
        /// <param name="strPassword">登錄密碼</param>
        /// <param name="objProxy">連接代理</param>
        public FTPHelper(Uri FtpUri, string strUserName, string strPassword, WebProxy objProxy)
        {
            this._Uri = new Uri(FtpUri.GetLeftPart(UriPartial.Authority));
            _DirectoryPath = FtpUri.AbsolutePath;
            if (!_DirectoryPath.EndsWith("/"))
            {
                _DirectoryPath += "/";
            }
            this._UserName = strUserName;
            this._Password = strPassword;
            this._Proxy = objProxy;
        }
        /// <summary>
        /// 構造函數
        /// </summary>
        public FTPHelper()
        {
            this._UserName = "anonymous";  //匿名用戶
            this._Password = "@anonymous";
            this._Uri = null;
            this._Proxy = null;
        }

        /// <summary>
        /// 析構函數
        /// </summary>
        ~FTPHelper()
        {
            if (Response != null)
            {
                Response.Close();
                Response = null;
            }
            if (Request != null)
            {
                Request.Abort();
                Request = null;
            }
        }
        #endregion


        #region 建立連接
        /// <summary>
        /// 建立FTP鏈接,返回響應對象
        /// </summary>
        /// <param name="uri">FTP地址</param>
        /// <param name="FtpMathod">操作命令</param>
        private FtpWebResponse Open(Uri uri, string FtpMathod)
        {
            try
            {
                Request = (FtpWebRequest)WebRequest.Create(uri);
                Request.Method = FtpMathod;
                Request.UseBinary = true;
                Request.KeepAlive = false;
                Request.Credentials = new NetworkCredential(this.UserName, this.Password);

                if (this.Proxy != null)
                {
                    Request.Proxy = this.Proxy;
                }
                return (FtpWebResponse)Request.GetResponse();
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        /// <summary>
        /// 建立FTP鏈接,返回請求對象
        /// </summary>
        /// <param name="uri">FTP地址</param>
        /// <param name="FtpMathod">操作命令</param>
        private FtpWebRequest OpenRequest(Uri uri, string FtpMathod)
        {
            try
            {
                Request = (FtpWebRequest)WebRequest.Create(uri);
                Request.Method = FtpMathod;
                Request.UseBinary = true;
                Request.KeepAlive = false;
                Request.Credentials = new NetworkCredential(this.UserName, this.Password);

                if (this.Proxy != null)
                {
                    Request.Proxy = this.Proxy;
                }
                return Request;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        #endregion


        #region 下載文件
        /// <summary>
        /// 從FTP服務器下載文件,使用與遠程文件同名的文件名來保存文件
        /// </summary>
        /// <param name="RemoteFileName">遠程文件名</param>
        /// <param name="LocalPath">本地路徑</param>

        public bool DownloadFile(string RemoteFileName, string LocalPath)
        {
            return DownloadFile(RemoteFileName, LocalPath, RemoteFileName);
        }
        /// <summary>
        /// 從FTP服務器下載文件,指定本地路徑和本地文件名
        /// </summary>
        /// <param name="RemoteFileName">遠程文件名</param>
        /// <param name="LocalPath">本地路徑</param>
        /// <param name="LocalFilePath">保存文件的本地路徑,后面帶有"\"</param>
        /// <param name="LocalFileName">保存本地的文件名</param>
        public bool DownloadFile(string RemoteFileName, string LocalPath, string LocalFileName)
        {
            byte[] bt = null;
            try
            {
                if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(LocalFileName) || !IsValidPathChars(LocalPath))
                {
                    throw new Exception("非法文件名或目錄名!");
                }
                if (!Directory.Exists(LocalPath))
                {
                    throw new Exception("本地文件路徑不存在!");
                }

                string LocalFullPath = Path.Combine(LocalPath, LocalFileName);
                if (File.Exists(LocalFullPath))
                {
                    throw new Exception("當前路徑下已經存在同名文件!");
                }
                bt = DownloadFile(RemoteFileName);
                if (bt != null)
                {
                    FileStream stream = new FileStream(LocalFullPath, FileMode.Create);
                    stream.Write(bt, 0, bt.Length);
                    stream.Flush();
                    stream.Close();
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 從FTP服務器下載文件,返回文件二進制數據
        /// </summary>
        /// <param name="RemoteFileName">遠程文件名</param>
        public byte[] DownloadFile(string RemoteFileName)
        {
            try
            {
                if (!IsValidFileChars(RemoteFileName))
                {
                    throw new Exception("非法文件名或目錄名!");
                }
                Response = Open(new Uri(this.Uri.ToString() + RemoteFileName), WebRequestMethods.Ftp.DownloadFile);
                Stream Reader = Response.GetResponseStream();

                MemoryStream mem = new MemoryStream(1024 * 500);
                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                int TotalByteRead = 0;
                while (true)
                {
                    bytesRead = Reader.Read(buffer, 0, buffer.Length);
                    TotalByteRead += bytesRead;
                    if (bytesRead == 0)
                        break;
                    mem.Write(buffer, 0, bytesRead);
                }
                if (mem.Length >= 0)
                {
                    return mem.ToArray();
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        #endregion


        #region 異步下載文件
        /// <summary>
        /// 從FTP服務器異步下載文件,指定本地路徑和本地文件名
        /// </summary>
        /// <param name="RemoteFileName">遠程文件名</param>        
        /// <param name="LocalPath">保存文件的本地路徑,后面帶有"\"</param>
        /// <param name="LocalFileName">保存本地的文件名</param>
        public void DownloadFileAsync(string RemoteFileName, string LocalPath, string LocalFileName)
        {
            //byte[] bt = null;
            try
            {
                if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(LocalFileName) || !IsValidPathChars(LocalPath))
                {
                    throw new Exception("非法文件名或目錄名!");
                }
                if (!Directory.Exists(LocalPath))
                {
                    throw new Exception("本地文件路徑不存在!");
                }

                string LocalFullPath = Path.Combine(LocalPath, LocalFileName);
                if (File.Exists(LocalFullPath))
                {
                    throw new Exception("當前路徑下已經存在同名文件!");
                }
                DownloadFileAsync(RemoteFileName, LocalFullPath);

            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 從FTP服務器異步下載文件,指定本地完整路徑文件名
        /// </summary>
        /// <param name="RemoteFileName">遠程文件名</param>
        /// <param name="LocalFullPath">本地完整路徑文件名</param>
        public void DownloadFileAsync(string RemoteFileName, string LocalFullPath)
        {
            try
            {
                if (!IsValidFileChars(RemoteFileName))
                {
                    throw new Exception("非法文件名或目錄名!");
                }
                if (File.Exists(LocalFullPath))
                {
                    throw new Exception("當前路徑下已經存在同名文件!");
                }
                MyWebClient client = new MyWebClient();

                client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
                client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(client_DownloadFileCompleted);
                client.Credentials = new NetworkCredential(this.UserName, this.Password);
                if (this.Proxy != null)
                {
                    client.Proxy = this.Proxy;
                }
                client.DownloadFileAsync(new Uri(this.Uri.ToString() + RemoteFileName), LocalFullPath);
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 異步下載文件完成之后觸發的事件
        /// </summary>
        /// <param name="sender">下載對象</param>
        /// <param name="e">數據信息對象</param>
        void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            if (DownloadDataCompleted != null)
            {
                DownloadDataCompleted(sender, e);
            }
        }

        /// <summary>
        /// 異步下載進度發生改變觸發的事件
        /// </summary>
        /// <param name="sender">下載對象</param>
        /// <param name="e">進度信息對象</param>
        void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            if (DownloadProgressChanged != null)
            {
                DownloadProgressChanged(sender, e);
            }
        }
        #endregion


        #region 上傳文件
        /// <summary>
        /// 上傳文件到FTP服務器
        /// </summary>
        /// <param name="LocalFullPath">本地帶有完整路徑的文件名</param>
        public bool UploadFile(string LocalFullPath)
        {
            return UploadFile(LocalFullPath, Path.GetFileName(LocalFullPath), false);
        }
        /// <summary>
        /// 上傳文件到FTP服務器
        /// </summary>
        /// <param name="LocalFullPath">本地帶有完整路徑的文件</param>
        /// <param name="OverWriteRemoteFile">是否覆蓋遠程服務器上面同名的文件</param>
        public bool UploadFile(string LocalFullPath, bool OverWriteRemoteFile)
        {
            return UploadFile(LocalFullPath, Path.GetFileName(LocalFullPath), OverWriteRemoteFile);
        }
        /// <summary>
        /// 上傳文件到FTP服務器
        /// </summary>
        /// <param name="LocalFullPath">本地帶有完整路徑的文件</param>
        /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param>
        public bool UploadFile(string LocalFullPath, string RemoteFileName)
        {
            return UploadFile(LocalFullPath, RemoteFileName, false);
        }
        /// <summary>
        /// 上傳文件到FTP服務器
        /// </summary>
        /// <param name="LocalFullPath">本地帶有完整路徑的文件名</param>
        /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param>
        /// <param name="OverWriteRemoteFile">是否覆蓋遠程服務器上面同名的文件</param>
        public bool UploadFile(string LocalFullPath, string RemoteFileName, bool OverWriteRemoteFile)
        {
            try
            {
                if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(Path.GetFileName(LocalFullPath)) || !IsValidPathChars(Path.GetDirectoryName(LocalFullPath)))
                {
                    throw new Exception("非法文件名或目錄名!");
                }
                if (File.Exists(LocalFullPath))
                {
                    FileStream Stream = new FileStream(LocalFullPath, FileMode.Open, FileAccess.Read);
                    byte[] bt = new byte[Stream.Length];
                    Stream.Read(bt, 0, (Int32)Stream.Length);   //注意,因為Int32的最大限制,最大上傳文件只能是大約2G多一點
                    Stream.Close();
                    return UploadFile(bt, RemoteFileName, OverWriteRemoteFile);
                }
                else
                {
                    throw new Exception("本地文件不存在!");
                }
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        /// <summary>
        /// 上傳文件到FTP服務器
        /// </summary>
        /// <param name="FileBytes">上傳的二進制數據</param>
        /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param>
        public bool UploadFile(byte[] FileBytes, string RemoteFileName)
        {
            if (!IsValidFileChars(RemoteFileName))
            {
                throw new Exception("非法文件名或目錄名!");
            }
            return UploadFile(FileBytes, RemoteFileName, false);
        }
        /// <summary>
        /// 上傳文件到FTP服務器
        /// </summary>
        /// <param name="FileBytes">文件二進制內容</param>
        /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param>
        /// <param name="OverWriteRemoteFile">是否覆蓋遠程服務器上面同名的文件</param>
        public bool UploadFile(byte[] FileBytes, string RemoteFileName, bool OverWriteRemoteFile)
        {
            try
            {
                if (!IsValidFileChars(RemoteFileName))
                {
                    throw new Exception("非法文件名!");
                }
                if (!OverWriteRemoteFile && FileExist(RemoteFileName))
                {
                    throw new Exception("FTP服務上面已經存在同名文件!");
                }
                OpenRequest(new Uri(this.Uri.ToString() + RemoteFileName), WebRequestMethods.Ftp.UploadFile);
                Stream requestStream = Request.GetRequestStream();
                MemoryStream mem = new MemoryStream(FileBytes);

                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                int TotalRead = 0;
                while (true)
                {
                    bytesRead = mem.Read(buffer, 0, buffer.Length);
                    if (bytesRead == 0)
                        break;
                    TotalRead += bytesRead;
                    requestStream.Write(buffer, 0, bytesRead);
                }
                requestStream.Close();
                Response = (FtpWebResponse)Request.GetResponse();
                mem.Close();
                mem.Dispose();
                FileBytes = null;
                return true;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        #endregion


        #region 異步上傳文件
        /// <summary>
        /// 異步上傳文件到FTP服務器
        /// </summary>
        /// <param name="LocalFullPath">本地帶有完整路徑的文件名</param>
        public void UploadFileAsync(string LocalFullPath)
        {
            UploadFileAsync(LocalFullPath, Path.GetFileName(LocalFullPath), false);
        }
        /// <summary>
        /// 異步上傳文件到FTP服務器
        /// </summary>
        /// <param name="LocalFullPath">本地帶有完整路徑的文件</param>
        /// <param name="OverWriteRemoteFile">是否覆蓋遠程服務器上面同名的文件</param>
        public void UploadFileAsync(string LocalFullPath, bool OverWriteRemoteFile)
        {
            UploadFileAsync(LocalFullPath, Path.GetFileName(LocalFullPath), OverWriteRemoteFile);
        }
        /// <summary>
        /// 異步上傳文件到FTP服務器
        /// </summary>
        /// <param name="LocalFullPath">本地帶有完整路徑的文件</param>
        /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param>
        public void UploadFileAsync(string LocalFullPath, string RemoteFileName)
        {
            UploadFileAsync(LocalFullPath, RemoteFileName, false);
        }
        /// <summary>
        /// 異步上傳文件到FTP服務器
        /// </summary>
        /// <param name="LocalFullPath">本地帶有完整路徑的文件名</param>
        /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param>
        /// <param name="OverWriteRemoteFile">是否覆蓋遠程服務器上面同名的文件</param>
        public void UploadFileAsync(string LocalFullPath, string RemoteFileName, bool OverWriteRemoteFile)
        {
            try
            {
                if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(Path.GetFileName(LocalFullPath)) || !IsValidPathChars(Path.GetDirectoryName(LocalFullPath)))
                {
                    throw new Exception("非法文件名或目錄名!");
                }
                if (!OverWriteRemoteFile && FileExist(RemoteFileName))
                {
                    throw new Exception("FTP服務上面已經存在同名文件!");
                }
                if (File.Exists(LocalFullPath))
                {
                    MyWebClient client = new MyWebClient();

                    client.UploadProgressChanged += new UploadProgressChangedEventHandler(client_UploadProgressChanged);
                    client.UploadFileCompleted += new UploadFileCompletedEventHandler(client_UploadFileCompleted);
                    client.Credentials = new NetworkCredential(this.UserName, this.Password);
                    if (this.Proxy != null)
                    {
                        client.Proxy = this.Proxy;
                    }
                    client.UploadFileAsync(new Uri(this.Uri.ToString() + RemoteFileName), LocalFullPath);

                }
                else
                {
                    throw new Exception("本地文件不存在!");
                }
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        /// <summary>
        /// 異步上傳文件到FTP服務器
        /// </summary>
        /// <param name="FileBytes">上傳的二進制數據</param>
        /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param>
        public void UploadFileAsync(byte[] FileBytes, string RemoteFileName)
        {
            if (!IsValidFileChars(RemoteFileName))
            {
                throw new Exception("非法文件名或目錄名!");
            }
            UploadFileAsync(FileBytes, RemoteFileName, false);
        }
        /// <summary>
        /// 異步上傳文件到FTP服務器
        /// </summary>
        /// <param name="FileBytes">文件二進制內容</param>
        /// <param name="RemoteFileName">要在FTP服務器上面保存文件名</param>
        /// <param name="OverWriteRemoteFile">是否覆蓋遠程服務器上面同名的文件</param>
        public void UploadFileAsync(byte[] FileBytes, string RemoteFileName, bool OverWriteRemoteFile)
        {
            try
            {

                if (!IsValidFileChars(RemoteFileName))
                {
                    throw new Exception("非法文件名!");
                }
                if (!OverWriteRemoteFile && FileExist(RemoteFileName))
                {
                    throw new Exception("FTP服務上面已經存在同名文件!");
                }
                string TempPath = System.Environment.GetFolderPath(Environment.SpecialFolder.Templates);
                if (!TempPath.EndsWith("\\"))
                {
                    TempPath += "\\";
                }
                string TempFile = TempPath + Path.GetRandomFileName();
                TempFile = Path.ChangeExtension(TempFile, Path.GetExtension(RemoteFileName));
                FileStream Stream = new FileStream(TempFile, FileMode.CreateNew, FileAccess.Write);
                Stream.Write(FileBytes, 0, FileBytes.Length);   //注意,因為Int32的最大限制,最大上傳文件只能是大約2G多一點
                Stream.Flush();
                Stream.Close();
                Stream.Dispose();
                _isDeleteTempFile = true;
                _UploadTempFile = TempFile;
                FileBytes = null;
                UploadFileAsync(TempFile, RemoteFileName, OverWriteRemoteFile);



            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }

        /// <summary>
        /// 異步上傳文件完成之后觸發的事件
        /// </summary>
        /// <param name="sender">下載對象</param>
        /// <param name="e">數據信息對象</param>
        void client_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e)
        {
            if (_isDeleteTempFile)
            {
                if (File.Exists(_UploadTempFile))
                {
                    File.SetAttributes(_UploadTempFile, FileAttributes.Normal);
                    File.Delete(_UploadTempFile);
                }
                _isDeleteTempFile = false;
            }
            if (UploadFileCompleted != null)
            {
                UploadFileCompleted(sender, e);
            }
        }

        /// <summary>
        /// 異步上傳進度發生改變觸發的事件
        /// </summary>
        /// <param name="sender">下載對象</param>
        /// <param name="e">進度信息對象</param>
        void client_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e)
        {
            if (UploadProgressChanged != null)
            {
                UploadProgressChanged(sender, e);
            }
        }
        #endregion


        #region 列出目錄文件信息
        /// <summary>
        /// 列出FTP服務器上面當前目錄的所有文件和目錄
        /// </summary>
        public FileStruct[] ListFilesAndDirectories()
        {
            Response = Open(this.Uri, WebRequestMethods.Ftp.ListDirectoryDetails);
            StreamReader stream = new StreamReader(Response.GetResponseStream(), Encoding.Default);
            string Datastring = stream.ReadToEnd();
            FileStruct[] list = GetList(Datastring);
            return list;
        }
        /// <summary>
        /// 列出FTP服務器上面當前目錄的所有文件
        /// </summary>
        public FileStruct[] ListFiles()
        {
            FileStruct[] listAll = ListFilesAndDirectories();
            List<FileStruct> listFile = new List<FileStruct>();
            foreach (FileStruct file in listAll)
            {
                if (!file.IsDirectory)
                {
                    listFile.Add(file);
                }
            }
            return listFile.ToArray();
        }

        /// <summary>
        /// 列出FTP服務器上面當前目錄的所有的目錄
        /// </summary>
        public FileStruct[] ListDirectories()
        {
            FileStruct[] listAll = ListFilesAndDirectories();
            List<FileStruct> listDirectory = new List<FileStruct>();
            foreach (FileStruct file in listAll)
            {
                if (file.IsDirectory)
                {
                    listDirectory.Add(file);
                }
            }
            return listDirectory.ToArray();
        }
        /// <summary>
        /// 獲得文件和目錄列表
        /// </summary>
        /// <param name="datastring">FTP返回的列表字符信息</param>
        private FileStruct[] GetList(string datastring)
        {
            List<FileStruct> myListArray = new List<FileStruct>();
            string[] dataRecords = datastring.Split('\n');
            FileListStyle _directoryListStyle = GuessFileListStyle(dataRecords);
            foreach (string s in dataRecords)
            {
                if (_directoryListStyle != FileListStyle.Unknown && s != "")
                {
                    FileStruct f = new FileStruct();
                    f.Name = "..";
                    switch (_directoryListStyle)
                    {
                        case FileListStyle.UnixStyle:
                            f = ParseFileStructFromUnixStyleRecord(s);
                            break;
                        case FileListStyle.WindowsStyle:
                            f = ParseFileStructFromWindowsStyleRecord(s);
                            break;
                    }
                    if (!(f.Name == "." || f.Name == ".."))
                    {
                        myListArray.Add(f);
                    }
                }
            }
            return myListArray.ToArray();
        }

        /// <summary>
        /// 從Windows格式中返回文件信息
        /// </summary>
        /// <param name="Record">文件信息</param>
        private FileStruct ParseFileStructFromWindowsStyleRecord(string Record)
        {
            FileStruct f = new FileStruct();
            string processstr = Record.Trim();
            string dateStr = processstr.Substring(0, 8);
            processstr = (processstr.Substring(8, processstr.Length - 8)).Trim();
            string timeStr = processstr.Substring(0, 7);
            processstr = (processstr.Substring(7, processstr.Length - 7)).Trim();
            DateTimeFormatInfo myDTFI = new CultureInfo("en-US", false).DateTimeFormat;
            myDTFI.ShortTimePattern = "t";
            f.CreateTime = DateTime.Parse(dateStr + " " + timeStr, myDTFI);
            if (processstr.Substring(0, 5) == "<DIR>")
            {
                f.IsDirectory = true;
                processstr = (processstr.Substring(5, processstr.Length - 5)).Trim();
            }
            else
            {
                string[] strs = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);   // true);
                processstr = strs[1];
                f.IsDirectory = false;
            }
            f.Name = processstr;
            return f;
        }


        /// <summary>
        /// 判斷文件列表的方式Window方式還是Unix方式
        /// </summary>
        /// <param name="recordList">文件信息列表</param>
        private FileListStyle GuessFileListStyle(string[] recordList)
        {
            foreach (string s in recordList)
            {
                if (s.Length > 10
                 && Regex.IsMatch(s.Substring(0, 10), "(-|d)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)(-|r)(-|w)(-|x)"))
                {
                    return FileListStyle.UnixStyle;
                }
                else if (s.Length > 8
                 && Regex.IsMatch(s.Substring(0, 8), "[0-9][0-9]-[0-9][0-9]-[0-9][0-9]"))
                {
                    return FileListStyle.WindowsStyle;
                }
            }
            return FileListStyle.Unknown;
        }

        /// <summary>
        /// 從Unix格式中返回文件信息
        /// </summary>
        /// <param name="Record">文件信息</param>
        private FileStruct ParseFileStructFromUnixStyleRecord(string Record)
        {
            FileStruct f = new FileStruct();
            string processstr = Record.Trim();
            f.Flags = processstr.Substring(0, 10);
            f.IsDirectory = (f.Flags[0] == 'd');
            processstr = (processstr.Substring(11)).Trim();
            _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);   //跳過一部分
            f.Owner = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);
            f.Group = _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);
            _cutSubstringFromStringWithTrim(ref processstr, ' ', 0);   //跳過一部分
            string yearOrTime = processstr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[2];
            if (yearOrTime.IndexOf(":") >= 0)  //time
            {
                processstr = processstr.Replace(yearOrTime, DateTime.Now.Year.ToString());
            }
            f.CreateTime = DateTime.Parse(_cutSubstringFromStringWithTrim(ref processstr, ' ', 8));
            f.Name = processstr;   //最后就是名稱
            return f;
        }

        /// <summary>
        /// 按照一定的規則進行字符串截取
        /// </summary>
        /// <param name="s">截取的字符串</param>
        /// <param name="c">查找的字符</param>
        /// <param name="startIndex">查找的位置</param>
        private string _cutSubstringFromStringWithTrim(ref string s, char c, int startIndex)
        {
            int pos1 = s.IndexOf(c, startIndex);
            string retString = s.Substring(0, pos1);
            s = (s.Substring(pos1)).Trim();
            return retString;
        }
        #endregion


        #region 目錄或文件存在的判斷
        /// <summary>
        /// 判斷當前目錄下指定的子目錄是否存在
        /// </summary>
        /// <param name="RemoteDirectoryName">指定的目錄名</param>
        public bool DirectoryExist(string RemoteDirectoryName)
        {
            try
            {
                if (!IsValidPathChars(RemoteDirectoryName))
                {
                    throw new Exception("目錄名非法!");
                }
                FileStruct[] listDir = ListDirectories();
                foreach (FileStruct dir in listDir)
                {
                    if (dir.Name == RemoteDirectoryName)
                    {
                        return true;
                    }
                }
                return false;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        /// <summary>
        /// 判斷一個遠程文件是否存在服務器當前目錄下面
        /// </summary>
        /// <param name="RemoteFileName">遠程文件名</param>
        public bool FileExist(string RemoteFileName)
        {
            try
            {
                if (!IsValidFileChars(RemoteFileName))
                {
                    throw new Exception("文件名非法!");
                }
                FileStruct[] listFile = ListFiles();
                foreach (FileStruct file in listFile)
                {
                    if (file.Name == RemoteFileName)
                    {
                        return true;
                    }
                }
                return false;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        #endregion


        #region 刪除文件
        /// <summary>
        /// 從FTP服務器上面刪除一個文件
        /// </summary>
        /// <param name="RemoteFileName">遠程文件名</param>
        public void DeleteFile(string RemoteFileName)
        {
            try
            {
                if (!IsValidFileChars(RemoteFileName))
                {
                    throw new Exception("文件名非法!");
                }
                Response = Open(new Uri(this.Uri.ToString() + RemoteFileName), WebRequestMethods.Ftp.DeleteFile);
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        #endregion


        #region 重命名文件
        /// <summary>
        /// 更改一個文件的名稱或一個目錄的名稱
        /// </summary>
        /// <param name="RemoteFileName">原始文件或目錄名稱</param>
        /// <param name="NewFileName">新的文件或目錄的名稱</param>
        public bool ReName(string RemoteFileName, string NewFileName)
        {
            try
            {
                if (!IsValidFileChars(RemoteFileName) || !IsValidFileChars(NewFileName))
                {
                    throw new Exception("文件名非法!");
                }
                if (RemoteFileName == NewFileName)
                {
                    return true;
                }
                if (FileExist(RemoteFileName))
                {
                    Request = OpenRequest(new Uri(this.Uri.ToString() + RemoteFileName), WebRequestMethods.Ftp.Rename);
                    Request.RenameTo = NewFileName;
                    Response = (FtpWebResponse)Request.GetResponse();

                }
                else
                {
                    throw new Exception("文件在服務器上不存在!");
                }
                return true;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        #endregion


        #region 拷貝、移動文件
        /// <summary>
        /// 把當前目錄下面的一個文件拷貝到服務器上面另外的目錄中,注意,拷貝文件之后,當前工作目錄還是文件原來所在的目錄
        /// </summary>
        /// <param name="RemoteFile">當前目錄下的文件名</param>
        /// <param name="DirectoryName">新目錄名稱。
        /// 說明:如果新目錄是當前目錄的子目錄,則直接指定子目錄。如: SubDirectory1/SubDirectory2 ;
        /// 如果新目錄不是當前目錄的子目錄,則必須從根目錄一級一級的指定。如: ./NewDirectory/SubDirectory1/SubDirectory2
        /// </param>
        /// <returns></returns>
        public bool CopyFileToAnotherDirectory(string RemoteFile, string DirectoryName)
        {
            string CurrentWorkDir = this.DirectoryPath;
            try
            {
                byte[] bt = DownloadFile(RemoteFile);
                GotoDirectory(DirectoryName);
                bool Success = UploadFile(bt, RemoteFile, false);
                this.DirectoryPath = CurrentWorkDir;
                return Success;
            }
            catch (Exception ep)
            {
                this.DirectoryPath = CurrentWorkDir;
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        /// <summary>
        /// 把當前目錄下面的一個文件移動到服務器上面另外的目錄中,注意,移動文件之后,當前工作目錄還是文件原來所在的目錄
        /// </summary>
        /// <param name="RemoteFile">當前目錄下的文件名</param>
        /// <param name="DirectoryName">新目錄名稱。
        /// 說明:如果新目錄是當前目錄的子目錄,則直接指定子目錄。如: SubDirectory1/SubDirectory2 ;
        /// 如果新目錄不是當前目錄的子目錄,則必須從根目錄一級一級的指定。如: ./NewDirectory/SubDirectory1/SubDirectory2
        /// </param>
        /// <returns></returns>
        public bool MoveFileToAnotherDirectory(string RemoteFile, string DirectoryName)
        {
            string CurrentWorkDir = this.DirectoryPath;
            try
            {
                if (DirectoryName == "")
                    return false;
                if (!DirectoryName.StartsWith("/"))
                    DirectoryName = "/" + DirectoryName;
                if (!DirectoryName.EndsWith("/"))
                    DirectoryName += "/";
                bool Success = ReName(RemoteFile, DirectoryName + RemoteFile);
                this.DirectoryPath = CurrentWorkDir;
                return Success;
            }
            catch (Exception ep)
            {
                this.DirectoryPath = CurrentWorkDir;
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        #endregion


        #region 建立、刪除子目錄
        /// <summary>
        /// 在FTP服務器上當前工作目錄建立一個子目錄
        /// </summary>
        /// <param name="DirectoryName">子目錄名稱</param>
        public bool MakeDirectory(string DirectoryName)
        {
            try
            {
                if (!IsValidPathChars(DirectoryName))
                {
                    throw new Exception("目錄名非法!");
                }
                if (DirectoryExist(DirectoryName))
                {
                    throw new Exception("服務器上面已經存在同名的文件名或目錄名!");
                }
                Response = Open(new Uri(this.Uri.ToString() + DirectoryName), WebRequestMethods.Ftp.MakeDirectory);
                return true;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        /// <summary>
        /// 從當前工作目錄中刪除一個子目錄
        /// </summary>
        /// <param name="DirectoryName">子目錄名稱</param>
        public bool RemoveDirectory(string DirectoryName)
        {
            try
            {
                if (!IsValidPathChars(DirectoryName))
                {
                    throw new Exception("目錄名非法!");
                }
                if (!DirectoryExist(DirectoryName))
                {
                    throw new Exception("服務器上面不存在指定的文件名或目錄名!");
                }
                Response = Open(new Uri(this.Uri.ToString() + DirectoryName), WebRequestMethods.Ftp.RemoveDirectory);
                return true;
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        #endregion


        #region 文件、目錄名稱有效性判斷
        /// <summary>
        /// 判斷目錄名中字符是否合法
        /// </summary>
        /// <param name="DirectoryName">目錄名稱</param>
        public bool IsValidPathChars(string DirectoryName)
        {
            char[] invalidPathChars = Path.GetInvalidPathChars();
            char[] DirChar = DirectoryName.ToCharArray();
            foreach (char C in DirChar)
            {
                if (Array.BinarySearch(invalidPathChars, C) >= 0)
                {
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 判斷文件名中字符是否合法
        /// </summary>
        /// <param name="FileName">文件名稱</param>
        public bool IsValidFileChars(string FileName)
        {
            char[] invalidFileChars = Path.GetInvalidFileNameChars();
            char[] NameChar = FileName.ToCharArray();
            foreach (char C in NameChar)
            {
                if (Array.BinarySearch(invalidFileChars, C) >= 0)
                {
                    return false;
                }
            }
            return true;
        }
        #endregion


        #region 目錄切換操作
        /// <summary>
        /// 進入一個目錄
        /// </summary>
        /// <param name="DirectoryName">
        /// 新目錄的名字。 
        /// 說明:如果新目錄是當前目錄的子目錄,則直接指定子目錄。如: SubDirectory1/SubDirectory2 ; 
        /// 如果新目錄不是當前目錄的子目錄,則必須從根目錄一級一級的指定。如: ./NewDirectory/SubDirectory1/SubDirectory2
        /// </param>
        public bool GotoDirectory(string DirectoryName)
        {
            string CurrentWorkPath = this.DirectoryPath;
            try
            {
                DirectoryName = DirectoryName.Replace("\\", "/");
                string[] DirectoryNames = DirectoryName.Split(new char[] { '/' });
                if (DirectoryNames[0] == ".")
                {
                    this.DirectoryPath = "/";
                    if (DirectoryNames.Length == 1)
                    {
                        return true;
                    }
                    Array.Clear(DirectoryNames, 0, 1);
                }
                bool Success = false;
                foreach (string dir in DirectoryNames)
                {
                    if (dir != null)
                    {
                        Success = EnterOneSubDirectory(dir);
                        if (!Success)
                        {
                            this.DirectoryPath = CurrentWorkPath;
                            return false;
                        }
                    }
                }
                return Success;

            }
            catch (Exception ep)
            {
                this.DirectoryPath = CurrentWorkPath;
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        /// <summary>
        /// 從當前工作目錄進入一個子目錄
        /// </summary>
        /// <param name="DirectoryName">子目錄名稱</param>
        private bool EnterOneSubDirectory(string DirectoryName)
        {
            try
            {
                if (DirectoryName.IndexOf("/") >= 0 || !IsValidPathChars(DirectoryName))
                {
                    throw new Exception("目錄名非法!");
                }
                if (DirectoryName.Length > 0 && DirectoryExist(DirectoryName))
                {
                    if (!DirectoryName.EndsWith("/"))
                    {
                        DirectoryName += "/";
                    }
                    _DirectoryPath += DirectoryName;
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ep)
            {
                ErrorMsg = ep.ToString();
                throw ep;
            }
        }
        /// <summary>
        /// 從當前工作目錄往上一級目錄
        /// </summary>
        public bool ComeoutDirectory()
        {
            if (_DirectoryPath == "/")
            {
                ErrorMsg = "當前目錄已經是根目錄!";
                throw new Exception("當前目錄已經是根目錄!");
            }
            char[] sp = new char[1] { '/' };

            string[] strDir = _DirectoryPath.Split(sp, StringSplitOptions.RemoveEmptyEntries);
            if (strDir.Length == 1)
            {
                _DirectoryPath = "/";
            }
            else
            {
                _DirectoryPath = String.Join("/", strDir, 0, strDir.Length - 1);
            }
            return true;

        }
        #endregion


        #region 重載WebClient,支持FTP進度
        internal class MyWebClient : WebClient
        {
            protected override WebRequest GetWebRequest(Uri address)
            {
                FtpWebRequest req = (FtpWebRequest)base.GetWebRequest(address);
                req.UsePassive = false;
                return req;
            }
        }
        #endregion
    }
}

 使用示例:

Uri ftpUrl = new Uri("ftp://192.168.1.100/");
FTPHelper ftp = new FTPHelper(ftpUrl, "用戶名", "密碼");
FileStruct[] files = ftp.ListFiles();
foreach (FileStruct fs in files)
{
if (fs.Name == filename)
{
    MessageUtil.ShowTips("服務器中已經含有" + filename + "文件");
    break;
}
}
bool result = ftp.UploadFile(filePosition);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM