zoukankan      html  css  js  c++  java
  • FTP操作类(支持异步)

        public delegate void DownloadProgressChangedEventHandle(string information, long currentprogress, long totalprogress, string filename);
        public delegate void DownloadFileCompletedEventHandle(string information, bool success, string filename);
        public delegate void UploadProgressChangedEventHandle(string information, long currentprogress, long totalprogress, string filename);
        public delegate void UploadFileCompletedEventHandle(string information, bool success, string filename);
    
        /// <summary>
        /// FTP 的摘要说明。
        /// </summary>
        public class FTPClient
        {
            private string strRemoteHost;
            private int strRemotePort;
            private string strRemotePath;
            private string strRemoteUser;
            private string strRemotePass;
            private Boolean bConnected;
    
            public event DownloadProgressChangedEventHandle DownloadProgressChanged;
            public event DownloadFileCompletedEventHandle DownloadFileCompleted;
            public event UploadProgressChangedEventHandle UploadProgressChanged;
            public event UploadFileCompletedEventHandle UploadFileCompleted;
    
            #region 内部变量
            /// <summary>
            /// 服务器返回的应答信息(包含应答码)
            /// </summary>
            private string strMsg;
            /// <summary>
            /// 服务器返回的应答信息(包含应答码)
            /// </summary>
            private string strReply;
            /// <summary>
            /// 服务器返回的应答码
            /// </summary>
            private int iReplyCode;
            /// <summary>
            /// 进行控制连接的socket
            /// </summary>
            private Socket socketControl;
            /// <summary>
            /// 传输模式
            /// </summary>
            private TransferType trType;
            /// <summary>
            /// 传输模式:二进制类型、ASCII类型
            /// </summary>
            public enum TransferType
            {
                /// <summary>
                /// Binary
                /// </summary>
                Binary,
                /// <summary>
                /// ASCII
                /// </summary>
                ASCII
            };
            /// <summary>
            /// 接收和发送数据的缓冲区
            /// </summary>
            private static int BLOCK_SIZE = 1024;
            Byte[] buffer = new Byte[BLOCK_SIZE];
            /// <summary>
            /// 编码方式
            /// </summary>
            Encoding ASCII = Encoding.Default;
    
            private AsyncOperation asyncOperation;
    
            #endregion
    
            #region 内部函数
    
    
    
    
            #region 构造函数
            /// <summary>
            /// 缺省构造函数
            /// </summary>
            //public FTPClient()
            //{
            //    strRemoteHost = "";
            //    strRemotePath = "";
            //    strRemoteUser = "";
            //    strRemotePass = "";
            //    strRemotePort = 21;
            //    bConnected = false;
            //}
    
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="remoteHost"></param>
            /// <param name="remotePath"></param>
            /// <param name="remoteUser"></param>
            /// <param name="remotePass"></param>
            /// <param name="remotePort"></param>
            public FTPClient(string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort)
            {
                IPAddress[] ips;
    
                ips = Dns.GetHostAddresses(remoteHost);
                strRemoteHost = ips[0].ToString();
                strRemotePath = remotePath;
                strRemoteUser = remoteUser;
                strRemotePass = remotePass;
                strRemotePort = remotePort;
                Connect();
            }
            #endregion
    
            #region 登陆
            /// <summary>
            /// FTP服务器IP地址
            /// </summary>
    
            public string RemoteHost
            {
                get
                {
                    return strRemoteHost;
                }
                set
                {
                    strRemoteHost = value;
                }
            }
            /// <summary>
            /// FTP服务器端口
            /// </summary>
            public int RemotePort
            {
                get
                {
                    return strRemotePort;
                }
                set
                {
                    strRemotePort = value;
                }
            }
            /// <summary>
            /// 当前服务器目录
            /// </summary>
            public string RemotePath
            {
                get
                {
                    return strRemotePath;
                }
                set
                {
                    strRemotePath = value;
                }
            }
            /// <summary>
            /// 登录用户账号
            /// </summary>
            public string RemoteUser
            {
                set
                {
                    strRemoteUser = value;
                }
            }
            /// <summary>
            /// 用户登录密码
            /// </summary>
            public string RemotePass
            {
                set
                {
                    strRemotePass = value;
                }
            }
    
            /// <summary>
            /// 是否登录
            /// </summary>
            public bool Connected
            {
                get
                {
                    return bConnected;
                }
            }
            #endregion
    
            #region 链接
            /// <summary>
            /// 建立连接 
            /// </summary>
            public void Connect()
            {
                socketControl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint ep = new IPEndPoint(IPAddress.Parse(RemoteHost), strRemotePort);
                // 链接
                try
                {
                    socketControl.Connect(ep);
                }
                catch (Exception)
                {
                    throw new IOException("Couldn't connect to remote server");
                }
    
                // 获取应答码
                ReadReply();
                if (iReplyCode != 220)
                {
                    DisConnect();
                    throw new IOException(strReply.Substring(4));
                }
    
                // 登陆
                SendCommand("USER " + strRemoteUser);
                if (!(iReplyCode == 331 || iReplyCode == 230))
                {
                    CloseSocketConnect();//关闭连接
                    throw new IOException(strReply.Substring(4));
                }
                if (iReplyCode != 230)
                {
                    SendCommand("PASS " + strRemotePass);
                    if (!(iReplyCode == 230 || iReplyCode == 202))
                    {
                        CloseSocketConnect();//关闭连接
                        throw new IOException(strReply.Substring(4));
                    }
                }
                bConnected = true;
    
                // 切换到目录
                ChDir(strRemotePath);
            }
    
    
            /// <summary>
            /// 关闭连接
            /// </summary>
            public void DisConnect()
            {
                if (socketControl != null)
                {
                    SendCommand("QUIT");
                }
                CloseSocketConnect();
            }
    
            #endregion
    
            #region 传输模式
    
            /// <summary>
            /// 设置传输模式
            /// </summary>
            /// <param name="ttType">传输模式</param>
            public void SetTransferType(TransferType ttType)
            {
                if (ttType == TransferType.Binary)
                {
                    SendCommand("TYPE I");//binary类型传输
                }
                else
                {
                    SendCommand("TYPE A");//ASCII类型传输
                }
                if (iReplyCode != 200)
                {
                    throw new IOException(strReply.Substring(4));
                }
                else
                {
                    trType = ttType;
                }
            }
    
    
            /// <summary>
            /// 获得传输模式
            /// </summary>
            /// <returns>传输模式<
    eturns>
            public TransferType GetTransferType()
            {
                return trType;
            }
    
            #endregion
    
            #region 文件操作
            /// <summary>
            /// 获得文件列表
            /// </summary>
            /// <param name="strMask">文件名的匹配字符串</param>
            /// <returns><
    eturns>
            public string[] Dir(string strMask)
            {
                // 建立链接
                if (!bConnected)
                {
                    Connect();
                }
    
                //建立进行数据连接的socket
                Socket socketData = CreateDataSocket();
    
                //传送命令
                SendCommand("NLST " + strMask);
                if (iReplyCode == 550)
                {
                    Put(strMask);
                    SendCommand("NLST " + strMask);
                }
                //分析应答代码
                if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226))
                {
                    throw new IOException(strReply.Substring(4));
                }
    
                //获得结果
                strMsg = "";
                while (true)
                {
                    int iBytes = socketData.Receive(buffer, buffer.Length, 0);
                    strMsg += ASCII.GetString(buffer, 0, iBytes);
                    if (iBytes < buffer.Length)
                    {
                        break;
                    }
                }
                strMsg = strMsg.Replace('
    ', ' ');
                char[] seperator = { '
    ' };
                string[] strsFileList = strMsg.Split(seperator, StringSplitOptions.RemoveEmptyEntries);
                socketData.Close();//数据socket关闭时也会有返回码
                if (iReplyCode != 226)
                {
                    ReadReply();
                    if (iReplyCode != 226)
                    {
                        throw new IOException(strReply.Substring(4));
                    }
                }
                return strsFileList;
            }
    
    
            /// <summary>
            /// 获取文件大小
            /// </summary>
            /// <param name="strFileName">文件名</param>
            /// <returns>文件大小<
    eturns>
            public long GetFileSize(string strFileName)
            {
                if (!bConnected)
                {
                    Connect();
                }
                SendCommand("SIZE " + Path.GetFileName(strFileName));
                long lSize = 0;
                if (iReplyCode == 213)
                {
                    lSize = Int64.Parse(strReply.Substring(4));
                }
                else
                {
                    throw new IOException(strReply.Substring(4));
                }
                return lSize;
            }
    
    
            /// <summary>
            /// 删除
            /// </summary>
            /// <param name="strFileName">待删除文件名</param>
            public void Delete(string strFileName)
            {
                if (!bConnected)
                {
                    Connect();
                }
                SendCommand("DELE " + strFileName);
                if (iReplyCode != 250)
                {
                    throw new IOException(strReply.Substring(4));
                }
            }
    
    
            /// <summary>
            /// 重命名(如果新文件名与已有文件重名,将覆盖已有文件)
            /// </summary>
            /// <param name="strOldFileName">旧文件名</param>
            /// <param name="strNewFileName">新文件名</param>
            public void Rename(string strOldFileName, string strNewFileName)
            {
                if (!bConnected)
                {
                    Connect();
                }
                SendCommand("RNFR " + strOldFileName);
                if (iReplyCode != 350)
                {
                    throw new IOException(strReply.Substring(4));
                }
                //  如果新文件名与原有文件重名,将覆盖原有文件
                SendCommand("RNTO " + strNewFileName);
                if (iReplyCode != 250)
                {
                    throw new IOException(strReply.Substring(4));
                }
            }
            #endregion
    
            #region 上传和下载
            /// <summary>
            /// 下载多个文件
            /// </summary>
            /// <param name="strFileNameMask">文件名的匹配字符串</param>
            /// <param name="strLocalFolder">本地目录(不得以/结束)</param>
            public void Get(string strFileNameMask, string strLocalFolder)
            {
                if (!bConnected)
                {
                    Connect();
                }
                string[] strFiles = Dir(strFileNameMask);
                foreach (string strFile in strFiles)
                {
                    if (!strFile.Equals(""))//一般来说strFiles的最后一个元素可能是空字符串
                    {
                        Get(strFile, strLocalFolder, strFile);
                    }
                }
            }
    
            /// <summary>
            /// 下载单个文件
            /// </summary>
            /// <param name="strRemoteFileName">要下载的文件名</param>
            /// <param name="strLocalFolder">本地目录(不得以/结束)</param>
            /// <param name="strLocalFileName">保存在本地时的文件名</param>
            public void Get(string strRemoteFileName, string strLocalFolder, string strLocalFileName)
            {
                if (!bConnected)
                {
                    Connect();
                }
    
                SetTransferType(TransferType.Binary);
    
                if (strLocalFileName.Equals(""))
                {
                    strLocalFileName = strRemoteFileName;
                }
                if (!File.Exists(strLocalFileName))
                {
                    Stream st = File.Create(strLocalFileName);
                    st.Close();
                }
    
                long fileSize = this.GetFileSize(strRemoteFileName);//mlh 获取文件总大小
    
                FileStream output = new
                 FileStream(strLocalFolder + "//" + strLocalFileName, FileMode.Create);
                Socket socketData = CreateDataSocket();
                SendCommand("RETR " + strRemoteFileName);
                if (!(iReplyCode == 150 || iReplyCode == 125
                 || iReplyCode == 226 || iReplyCode == 250))
                {
                    throw new IOException(strReply.Substring(4));
                }
                long num = 0; //mlh 记录总的上传大小
                while (true)
                {
                    int iBytes = socketData.Receive(buffer, buffer.Length, 0);
                    output.Write(buffer, 0, iBytes);
                    num += iBytes;
                    if (DownloadProgressChanged != null)
                    {
                        if (asyncOperation != null)
                        {
                            asyncOperation.Post((object data) =>
                            {
                                DownloadProgressChanged("", num, fileSize, strRemoteFileName);
                            }, null);
                        }
                        else
                            DownloadProgressChanged("", num, fileSize, strRemoteFileName);
    
                    }
                    if (iBytes <= 0)
                    {
                        break;
                    }
                }
                output.Close();
                if (socketData.Connected)
                {
                    socketData.Close();
                }
                if (!(iReplyCode == 226 || iReplyCode == 250))
                {
                    ReadReply();
                    if (!(iReplyCode == 226 || iReplyCode == 250))
                    {
                        throw new IOException(strReply.Substring(4));
                    }
                }
    
                if (asyncOperation != null)
                {
                    asyncOperation.Post((object data) =>
                    {
                        DownloadFileCompleted("", true, strRemoteFileName);
                    }, null);
                }
                else
                    DownloadFileCompleted("", true, strRemoteFileName);
            }
    
            /// <summary>
            /// 异步下载多个文件
            /// </summary>
            /// <param name="strFileNameMask"></param>
            /// <param name="strLocalFolder"></param>
            public void GetAsync(string strFileNameMask, string strLocalFolder)
            {
                asyncOperation = AsyncOperationManager.CreateOperation(null);
                Thread threadGet = new Thread(new ThreadStart(() => { Get(strFileNameMask, strLocalFolder); }));
                threadGet.IsBackground = true;
                threadGet.Start();
            }
    
            /// <summary>
            /// 异步下载单个文件
            /// </summary>
            /// <param name="strFileNameMask"></param>
            /// <param name="strLocalFolder"></param>
            /// <param name="strLocalFileName"></param>
            public void GetAsync(string strFileNameMask, string strLocalFolder, string strLocalFileName)
            {
                asyncOperation = AsyncOperationManager.CreateOperation(null);
                Thread threadGet = new Thread(new ThreadStart(() => { Get(strFileNameMask, strLocalFolder, strLocalFileName); }));
                threadGet.IsBackground = true;
                threadGet.Start();
            }
    
            /// <summary>
            /// 上传多个文件
            /// </summary>
            /// <param name="strFolder">本地目录(不得以/结束)</param>
            /// <param name="strFileNameMask">文件名匹配字符(可以包含*和?)</param>
            public void Put(string strFolder, string strFileNameMask)
            {
                string[] strFiles = Directory.GetFiles(strFolder, strFileNameMask);
                foreach (string strFile in strFiles)
                {
                    //strFile是完整的文件名(包含路径)
                    Put(strFile);
                }
            }
    
            /// <summary>
            /// 上传一个文件
            /// </summary>
            /// <param name="strFileName">本地文件名</param>
            public void Put(string strFileName)
            {
                if (!bConnected)
                {
                    Connect();
                }
                Socket socketData = CreateDataSocket();
                SendCommand("STOR " + Path.GetFileName(strFileName));
                if (!(iReplyCode == 125 || iReplyCode == 150))
                {
                    throw new IOException(strReply.Substring(4));
                }
    
                FileStream input = new
                 FileStream(strFileName, FileMode.Open);
    
                long num = 0;//mlh 当前上传大小
                long fileSize = input.Length;//mlh 文件总大小
                int iBytes = 0;
                while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0)
                {
                    num += iBytes;
                    if (UploadProgressChanged != null)
                        UploadProgressChanged("", num, fileSize, strFileName);
                    socketData.Send(buffer, iBytes, 0);
                }
                input.Close();
                if (socketData.Connected)
                {
                    socketData.Close();
                }
                if (!(iReplyCode == 226 || iReplyCode == 250))
                {
                    ReadReply();
                    if (!(iReplyCode == 226 || iReplyCode == 250))
                    {
                        throw new IOException(strReply.Substring(4));
                    }
                }
                if (UploadFileCompleted != null)
                    UploadFileCompleted("", true, strFileName);
            }
    
            /// <summary>
            /// 异步上传多个文件
            /// </summary>
            /// <param name="strFolder"></param>
            /// <param name="strFileNameMask"></param>
            public void PutAsync(string strFolder, string strFileNameMask)
            {
                asyncOperation = AsyncOperationManager.CreateOperation(null);
                Thread threadGet = new Thread(new ThreadStart(() => { Put(strFolder, strFileNameMask); }));
                threadGet.IsBackground = true;
                threadGet.Start();
            }
    
            /// <summary>
            /// 异步上传多个文件
            /// </summary>
            /// <param name="strFileName"></param>
            public void PutAsync(string strFileName)
            {
                asyncOperation = AsyncOperationManager.CreateOperation(null);
                Thread threadGet = new Thread(new ThreadStart(() => { Put(strFileName); }));
                threadGet.IsBackground = true;
                threadGet.Start();
            }
    
            #endregion
    
            #region 目录操作
            /// <summary>
            /// 创建目录
            /// </summary>
            /// <param name="strDirName">目录名</param>
            public void MkDir(string strDirName)
            {
                if (!bConnected)
                {
                    Connect();
                }
                SendCommand("MKD " + strDirName);
                if (iReplyCode != 257)
                {
                    throw new IOException(strReply.Substring(4));
                }
            }
    
    
            /// <summary>
            /// 删除目录
            /// </summary>
            /// <param name="strDirName">目录名</param>
            public void RmDir(string strDirName)
            {
                if (!bConnected)
                {
                    Connect();
                }
                SendCommand("RMD " + strDirName);
                if (iReplyCode != 250)
                {
                    throw new IOException(strReply.Substring(4));
                }
            }
    
    
            /// <summary>
            /// 改变目录
            /// </summary>
            /// <param name="strDirName">新的工作目录名</param>
            public void ChDir(string strDirName)
            {
                if (strDirName.Equals(".") || strDirName.Equals(""))
                {
                    return;
                }
                if (!bConnected)
                {
                    Connect();
                }
                SendCommand("CWD " + strDirName);
                if (iReplyCode != 250)
                {
                    throw new IOException(strReply.Substring(4));
                }
                this.strRemotePath = strDirName;
            }
    
            /// <summary>
            /// 列目录
            /// </summary>
            /// <param name="strDirName"></param>
            public string[] ListDir()
            {
                if (!bConnected)
                {
                    Connect();
                }
                //建立进行数据连接的socket
                Socket socketData = CreateDataSocket();
                SendCommand("LIST");
                if (iReplyCode != 150)
                {
                    throw new IOException(strReply.Substring(4));
                }
    
    
    
                //获得结果
                strMsg = "";
                while (true)
                {
                    int iBytes = socketData.Receive(buffer, buffer.Length, 0);
                    strMsg += ASCII.GetString(buffer, 0, iBytes);
                    if (iBytes < buffer.Length)
                    {
                        break;
                    }
                }
                strMsg = strMsg.Replace('
    ', ' ');
                char[] seperator = { '
    ' };
                string[] strsFileList = strMsg.Split(seperator);
                socketData.Close();//数据socket关闭时也会有返回码
                if (iReplyCode != 226)
                {
                    ReadReply();
                    if (iReplyCode != 226)
                    {
                        throw new IOException(strReply.Substring(4));
                    }
                }
                return strsFileList;
            }
    
    
            #endregion
    
    
            /// <summary>
            /// 将一行应答字符串记录在strReply和strMsg
            /// 应答码记录在iReplyCode
            /// </summary>
            private void ReadReply()
            {
                strMsg = "";
                strReply = ReadLine();
                iReplyCode = Int32.Parse(strReply.Substring(0, 3));
            }
    
            /// <summary>
            /// 建立进行数据连接的socket
            /// </summary>
            /// <returns>数据连接socket<
    eturns>
            private Socket CreateDataSocket()
            {
                SendCommand("PASV");
                if (iReplyCode != 227)
                {
                    throw new IOException(strReply.Substring(4));
                }
                int index1 = strReply.IndexOf('(');
                int index2 = strReply.IndexOf(')');
                string ipData =
                 strReply.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 strReply: " +
                         strReply);
                    }
                    if (ch == ',' || i + 1 == len)
                    {
                        try
                        {
                            parts[partCount++] = Int32.Parse(buf);
                            buf = "";
                        }
                        catch (Exception)
                        {
                            throw new IOException("Malformed PASV strReply: " +
                             strReply);
                        }
                    }
                }
                string ipAddress = parts[0] + "." + parts[1] + "." +
                 parts[2] + "." + parts[3];
                int port = (parts[4] << 8) + parts[5];
                Socket s = new
                 Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint ep = new
                 IPEndPoint(IPAddress.Parse(ipAddress), port);
                try
                {
                    s.Connect(ep);
                }
                catch (Exception)
                {
                    throw new IOException("Can't connect to remote server");
                }
                return s;
            }
    
    
            /// <summary>
            /// 关闭socket连接(用于登录以前)
            /// </summary>
            private void CloseSocketConnect()
            {
                if (socketControl != null)
                {
                    socketControl.Close();
                    socketControl = null;
                }
                bConnected = false;
            }
    
            /// <summary>
            /// 读取Socket返回的所有字符串
            /// </summary>
            /// <returns>包含应答码的字符串行<
    eturns>
            private string ReadLine()
            {
                while (true)
                {
                    int iBytes = socketControl.Receive(buffer, buffer.Length, 0);
                    strMsg += ASCII.GetString(buffer, 0, iBytes);
                    if (iBytes < buffer.Length)
                    {
                        break;
                    }
                }
                char[] seperator = new char[] { '
    ' };
                string[] mess = strMsg.Split(seperator);
                if (strMsg.Length > 2)
                {
                    strMsg = mess[mess.Length - 2];
                    //seperator[0]是10,换行符是由13和0组成的,分隔后10后面虽没有字符串,
                    //但也会分配为空字符串给后面(也是最后一个)字符串数组,
                    //所以最后一个mess是没用的空字符串
                    //但为什么不直接取mess[0],因为只有最后一行字符串应答码与信息之间有空格
                }
                else
                {
                    strMsg = mess[0];
                }
                if (!strMsg.Substring(3, 1).Equals(" "))//返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串)
                {
                    return ReadLine();
                }
                return strMsg;
            }
    
    
            /// <summary>
            /// 发送命令并获取应答码和最后一行应答字符串
            /// </summary>
            /// <param name="strCommand">命令</param>
            private void SendCommand(string strCommand)
            {
                Byte[] cmdBytes = ASCII.GetBytes((strCommand + "
    ").ToCharArray());
                socketControl.Send(cmdBytes, cmdBytes.Length, 0);
                ReadReply();
            }
    
            #endregion
        }
    View Code

    ps:在实际使用过程中发现由于BLOCK_SIZE设置太小导致DownloadProgressChanged事件触发过于频繁,结果界面会卡顿,所以具体多少可以自己调试设置

  • 相关阅读:
    Elementary Methods in Number Theory Exercise 1.2.25
    Elementary Methods in Number Theory Exercise 1.2.14
    图解欧几里德算法
    图解欧几里德算法
    Elementary Methods in Number Theory Exercise 1.2.14
    Android中的长度单位详解(dp、sp、px、in、pt、mm)
    分享下多年积累的对JAVA程序员成长之路的总结
    android异常之都是deamon惹的祸The connection to adb is down, and a severe error has occured.
    TomatoCartv1.1.8.2部署时报错
    JavaScript浏览器对象之二Document对象
  • 原文地址:https://www.cnblogs.com/xm_cpppp/p/3612468.html
Copyright © 2011-2022 走看看