注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

淡忘邻人

二十七,始发愤

 
 
 

日志

 
 
 
 

FTP 类  

2010-06-30 21:26:14|  分类: C# |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

FtpClient.cs

 //// <summary>
    /// FtpClient 的摘要说明。
    /// </summary>
    public class FtpClient : IDisposable
    ...{
        私有变量#region 私有变量

        private string _serverAddress;
        private int _serverPort;
        private string _remotePath;
        private string _loginUser;
        private string _loginPassword;
        private bool _connected;
        private FtpTransferType _transferType;
        private int _blockSize = 512;

        //// <summary>
        /// 服务器返回的应答信息。
        /// </summary>
        private FtpReply _reply;

        //// <summary>
        /// 进行控制连接的socket
        /// </summary>
        private Socket _socketControl;

        #endregion

        // 构造方法
        构造方法#region 构造方法

        /**//// <summary>
        /// 构造方法。
        /// </summary>
        public FtpClient() : this("localhost", "anonymous", "
anonymous@anonymous.net", 21)
        ...{
        }

        /**//// <summary>
        /// 构造方法。
        /// </summary>
        /// <param name="serverAddress"></param>
        /// <param name="loginUser"></param>
        /// <param name="loginPassword"></param>
        /// <param name="serverPort"></param>
        public FtpClient(string serverAddress, string loginUser, string loginPassword, int serverPort)
        {
            _serverAddress = serverAddress;
            _loginUser = loginUser;
            _loginPassword = loginPassword;
            _serverPort = serverPort;

            this._remotePath = string.Empty;
        }

        #endregion

        // 属性
        BlockSize 接收和发送数据的缓冲区大小#region BlockSize 接收和发送数据的缓冲区大小

        /**//// <summary>
        /// 获取或设置接收和发送数据的缓冲区大小,默认为 1024 。
        /// </summary>
        public int BlockSize
        ...{
            get
            ...{
                return this._blockSize;
            }
            set
            ...{
                this._blockSize = value;
            }
        }

        #endregion

        ServerAddress Ftp 服务器地址#region ServerAddress Ftp 服务器地址

        /**//// <summary>
        /// Ftp 服务器地址。默认为 localhost 。
        /// </summary>
        public string ServerAddress
        {
            get
            {
                return _serverAddress;
            }
            set
            ...{
                _serverAddress = value;
            }
        }

        #endregion

        ServerPort Ftp 服务器端口#region ServerPort Ftp 服务器端口

        /**//// <summary>
        /// Ftp 服务器端口。默认为 21 。
        /// </summary>
        public int ServerPort
        {
            get
            {
                return _serverPort;
            }
            set
            {
                _serverPort = value;
            }
        }

        #endregion

        RemotePath 当前服务器目录#region RemotePath 当前服务器目录

        /**//// <summary>
        /// 当前服务器目录。
        /// </summary>
        public string RemotePath
        {
            get
            {
                return _remotePath;
            }
            set
            {
                _remotePath = value;
            }
        }

        #endregion

        LoginUser 登录用户账号#region LoginUser 登录用户账号

        /**//// <summary>
        /// 登录用户账号。默认为 anonymous 。
        /// </summary>
        public string LoginUser
        {
            set
            {
                _loginUser = value;
            }
        }

        #endregion

        LoginPassword 用户登录密码#region LoginPassword 用户登录密码

        /**//// <summary>
        /// 用户登录密码。默认为
anonymous@anonymous.net
        /// </summary>
        public string LoginPassword
        ...{
            set
            ...{
                _loginPassword = value;
            }
        }

        #endregion

        Connected 是否登录#region Connected 是否登录

        /**//// <summary>
        /// 是否登录
        /// </summary>
        public bool Connected
        {
            get
            {
                return _connected;
            }
        }

        #endregion

 // 接口
        IDisposable 成员#region IDisposable 成员

        private bool disposed = false;

        /**//// <summary>
        /// <see cref="IDisposable"/> 接口的实现方法。
        /// </summary>
        void IDisposable.Dispose()
        ...{
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        /**//// <summary>
        /// 释放由 <see cref="FtpClient"/> 使用的非托管资源,并可根据需要处置托管资源。
        /// </summary>
        /// <param name="isDisposing">指示当前是否是被 Dispose() 方法调用。</param>
        protected virtual void Dispose(bool isDisposing)
        ...{
            if(!this.disposed)
            ...{
                if(isDisposing)
                ...{
                    // 释放托管的资源
                    if(this._socketControl!= null)
                    ...{
                        this.Close();
                    }
                }

                // 释放非托管的资源

                // 标记资源已经释放
                this.disposed = true;
            }
        }

        #endregion

        // 私有方法
        ReadReply#region ReadReply

        /**//// <summary>
        /// 将一行应答字符串记录在this._reply.Message和this._strMsg
        /// 应答码记录在this._reply.Code
        /// </summary>
        private FtpReply ReadReply()
        ...{
            this._reply = null;
            string message = ReadLine();
            this._reply = message.Length < 3 ? null : new FtpReply(Int32.Parse(message.Substring(0, 3)), message);
            return this._reply;
        }

        #endregion

        CreateDataSocket 建立进行数据连接的socket#region CreateDataSocket 建立进行数据连接的socket

        /**//// <summary>
        /// 建立进行数据连接的socket
        /// </summary>
        /// <returns>数据连接socket</returns>
        private Socket CreateDataSocket()
        ...{
            SendCommand("PASV");

            if(this._reply.Code != 227)
            ...{
                throw new FtpClientException(this._reply.Message.Substring(4));
            }

            int index1 = this._reply.Message.IndexOf('(');
            int index2 = this._reply.Message.IndexOf(')');
            string ipData = this._reply.Message.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 FtpClientException("Malformed PASV result: " + this._reply.Message);
                }
                if(ch == ',' || i + 1 == len)
                ...{
                    try
                    ...{
                        parts[partCount++] = Int32.Parse(buf);
                        buf = "";
                    }
                    catch (Exception)
                    ...{
                        throw new FtpClientException("Malformed PASV result (not supported?): " + this._reply.Message);
                    }
                }
            }

            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 ex)
            ...{
                throw new FtpClientException(string.Format("Can't connect to remote server {0} .", ipAddress), ex);
            }
            return s;
        }

        #endregion

        CloseSocketConnect 关闭socket连接(用于登录以前)#region CloseSocketConnect 关闭socket连接(用于登录以前)

        /**//// <summary>
        /// 关闭socket连接(用于登录以前)
        /// </summary>
        private void CloseSocketConnect()
        ...{
            if(this._socketControl!= null)
            ...{
                this._socketControl.Close();
                this._socketControl = null;
            }
            _connected = false;
        }

        #endregion

        ReadLine 读取Socket返回的所有字符串#region ReadLine 读取Socket返回的所有字符串

        /**//// <summary>
        /// 读取Socket返回的所有字符串
        /// </summary>
        /// <returns>包含应答码的字符串行</returns>
        private string ReadLine()
        ...{
            string message = string.Empty;

            byte[] buffer = new byte[this._blockSize];
            while(true)
            ...{
                Thread.Sleep(10);

                int iBytes = this._socketControl.Receive(buffer, buffer.Length, 0);
                message += Encoding.Default.GetString(buffer, 0, iBytes);
                if(iBytes < buffer.Length)
                ...{
                    break;
                }
            }

            string[] mess = StringHelper.Split(StringHelper.TrimEnd(message, true, " "), true, " ");
            if(mess.Length > 2)
            ...{
                message = mess[mess.Length-2];
                //seperator[0]是10,换行符是由13和0组成的,分隔后10后面虽没有字符串,
                //但也会分配为空字符串给后面(也是最后一个)字符串数组,
                //所以最后一个mess是没用的空字符串
                //但为什么不直接取mess[0],因为只有最后一行字符串应答码与信息之间有空格
            }
            else
            ...{
                message = mess[0];
            }
            if(message.Length > 3 && message.Substring(3, 1) != " ")//返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串)
            ...{
                return ReadLine();
            }

            return message;
        }

        #endregion

        SendCommand 发送命令并获取应答码和最后一行应答字符串#region SendCommand 发送命令并获取应答码和最后一行应答字符串

        /**//// <summary>
        /// 发送命令并获取应答码和最后一行应答字符串。
        /// </summary>
        /// <param name="command">命令</param>
        public FtpReply SendCommand(string command)
        ...{
            char[] charList = (command + " ").ToCharArray();
            Byte[] cmdBytes = Encoding.Default.GetBytes(charList);
            this._socketControl.Send(cmdBytes, cmdBytes.Length, 0);
            return this.ReadReply();
        }

        #endregion

        // 公共方法
        Connect 建立连接#region Connect 建立连接

        /**//// <summary>
        /// 建立连接
        /// </summary>
        public void Connect()
        ...{
            IPAddress address = null;
            if(RegexUtility.IsIP(this._serverAddress))
            ...{
                address = IPAddress.Parse(this._serverAddress);
            }
            else
            ...{
                try
                ...{
                    IPHostEntry host = Dns.GetHostByName(this._serverAddress);
                    if(host.AddressList.Length != 0)
                    ...{
                        address = host.AddressList[0];
                    }
                }
                catch(Exception ex)
                ...{
                    throw new FtpClientException(string.Format("获取 Ftp 服务器主机地址出错:{0}", ex.Message), ex);
                }
            }

            if(address == null)
            ...{
                throw new FtpClientException(string.Format("无法获取远程主机 {0} 的 IP 地址。", this._serverAddress));
            }

            this._socketControl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ep = new IPEndPoint(address, _serverPort);

            // 链接
            try
            ...{
                this._socketControl.Connect(ep);
            }
            catch(Exception ex)
            ...{
                throw new FtpClientException(string.Format("无法连接到远程服务器 {0} 。", address.ToString()), ex);
            }

            // 获取应答码
            ReadReply();
            if(this._reply.Code != 220)
            ...{
                Close();
                throw new FtpClientException(this._reply.Message.Substring(4));
            }

            // 登陆
            SendCommand("USER " + _loginUser);
            if(!(this._reply.Code == 331 || this._reply.Code == 230))
            ...{
                //关闭连接
                CloseSocketConnect();
                throw new FtpClientException(this._reply.Message.Substring(4));
            }
            if(this._reply.Code != 230)
            ...{
                SendCommand("PASS " + _loginPassword);
                if(!(this._reply.Code == 230 || this._reply.Code == 202))
                ...{
                    //关闭连接
                    CloseSocketConnect();
                    throw new FtpClientException(this._reply.Message.Substring(4));
                }
            }

            _connected = true;

            // 切换到目录
            ChangeDirectory(_remotePath);
        }

        #endregion

        EnsureConnected 确保已经连接到服务器#region EnsureConnected 确保已经连接到服务器

        /**//// <summary>
        /// 确保已经连接到服务器。
        /// </summary>
        protected void EnsureConnected()
        ...{
            if(!_connected)
            ...{
                Connect();
            }
        }

        #endregion

        Close 关闭连接#region Close 关闭连接

        /**//// <summary>
        /// 关闭连接
        /// </summary>
        public void Close()
        ...{
            if(this._socketControl != null)
            ...{
                SendCommand("QUIT");
            }

            CloseSocketConnect();
        }

        #endregion

        TransferType 获取或设置传输模式#region TransferType 获取或设置传输模式

        /**//// <summary>
        /// 获取或设置传输模式
        /// </summary>
        public FtpTransferType TransferType
        ...{
            get
            ...{
                return this._transferType;
            }
            set
            ...{
                if(value != this._transferType)
                ...{
                    if(value == FtpTransferType.Binary)
                    ...{
                        SendCommand("TYPE I");
                    }
                    else
                    ...{
                        SendCommand("TYPE A");
                    }

                    if(this._reply.Code != 200)
                    ...{
                        throw new FtpClientException(this._reply.Message.Substring(4));
                    }
                    else
                    ...{
                        this._transferType = value;
                    }
                }
            }
        }
   
        #endregion

        Dir 获得文件列表#region Dir 获得文件列表

        /**//// <summary>
        /// 获得文件列表。
        /// </summary>
        /// <returns></returns>
        public string[] Dir()
        ...{
            // 确保已连接上服务器
            this.EnsureConnected();

            //建立进行数据连接的socket
            Socket socketData = CreateDataSocket();
  
            //传送命令
            SendCommand("NLST");

            //分析应答代码
            if(this._reply.Code == 550)
            ...{
                return new string[0];
            }

            if(!(this._reply.Code == 150 || this._reply.Code == 125 || this._reply.Code == 226))
            ...{
                throw new FtpClientException(this._reply.Message.Substring(4));
            }

            //获得结果
            string message = string.Empty;
            byte[] buffer = new byte[this._blockSize];
            while(true)
            ...{
                int iBytes = socketData.Receive(buffer, buffer.Length, 0);
                message += Encoding.Default.GetString(buffer, 0, iBytes);
                if(iBytes < buffer.Length)
                ...{
                    break;
                }
            }

            string[] strsFileList = StringHelper.Split(StringHelper.TrimEnd(message, false, " "), false, " ");
            socketData.Close();//数据socket关闭时也会有返回码
            if(this._reply.Code != 226)
            ...{
                ReadReply();
                if(this._reply.Code != 226)
                ...{
                    throw new FtpClientException(this._reply.Message.Substring(4));
                }
            }
            return strsFileList;
        }

        #endregion

        GetFileSize 获取文件大小#region GetFileSize 获取文件大小

        /**//// <summary>
        /// 获取文件大小
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <returns>文件大小</returns>
        private long GetFileSize(string fileName)
        ...{
            // 确保已连接上服务器
            this.EnsureConnected();

            SendCommand("SIZE " + fileName);

            long lSize = 0;
            if(this._reply.Code == 213)
            ...{
                lSize = Int64.Parse(this._reply.Message.Substring(4));
            }
            else
            ...{
                throw new FtpClientException(this._reply.Message.Substring(4));
            }
            return lSize;
        }

        #endregion

        Delete 删除#region Delete 删除

        /**//// <summary>
        /// 删除
        /// </summary>
        /// <param name="fileName">待删除文件名</param>
        public void Delete(string fileName)
        ...{
            // 确保已连接上服务器
            this.EnsureConnected();

            SendCommand("DELE " + fileName);
            if(this._reply.Code != 250)
            ...{
                throw new FtpClientException(this._reply.Message.Substring(4));
            }
        }

        #endregion

        Rename 重命名文件(如果新文件名与已有文件重名,将覆盖已有文件)#region Rename 重命名文件(如果新文件名与已有文件重名,将覆盖已有文件)

        /**//// <summary>
        /// 重命名(如果新文件名与已有文件重名,将覆盖已有文件)。
        /// </summary>
        /// <param name="oldFileName">旧文件名</param>
        /// <param name="newFileName">新文件名</param>
        public void Rename(string oldFileName,string newFileName)
        ...{
            // 确保已连接上服务器
            this.EnsureConnected();

            SendCommand("RNFR " + oldFileName);
            if(this._reply.Code != 350)
            ...{
                throw new FtpClientException(this._reply.Message.Substring(4));
            }

            //  如果新文件名与原有文件重名,将覆盖原有文件
            SendCommand("RNTO " + newFileName);
            if(this._reply.Code != 250)
            ...{
                throw new FtpClientException(this._reply.Message.Substring(4));
            }
        }
        #endregion

        Download 下载文件#region Download 下载文件

        /**//// <summary>
        /// 下载一个文件
        /// </summary>
        /// <param name="remoteFileName">远程服务器上的文件路径名。</param>
        /// <param name="localFileName">将文件保存到的本地路径名。</param>
        public void DownloadFile(string remoteFileName, string localFileName)
        ...{
            // 确保已连接上服务器
            this.EnsureConnected();

            this.TransferType = FtpTransferType.Binary;

            if(localFileName == string.Empty)
            ...{
                localFileName = remoteFileName;
            }
            string path = Path.GetDirectoryName(localFileName);
            if(!Directory.Exists(path))
            ...{
                Directory.CreateDirectory(path);
            }

            FileStream output = new FileStream(localFileName, FileMode.Create);
            Socket socketData = CreateDataSocket();
            SendCommand("RETR " + remoteFileName);
            if(!(this._reply.Code == 150 || this._reply.Code == 125 || this._reply.Code == 226 || this._reply.Code == 250))
            ...{
                throw new FtpClientException(this._reply.Message.Substring(4));
            }

            byte[] buffer = new byte[this._blockSize];
            while(true)
            ...{
                int iBytes = socketData.Receive(buffer, buffer.Length, 0);
                output.Write(buffer,0,iBytes);
                if(iBytes <= 0)
                ...{
                    break;
                }
            }

            output.Close();
            if(socketData.Connected)
            ...{
                socketData.Close();
            }

            if(!(this._reply.Code == 226 || this._reply.Code == 250))
            ...{
                ReadReply();
                if(!(this._reply.Code == 226 || this._reply.Code == 250))
                ...{
                    throw new FtpClientException(this._reply.Message.Substring(4));
                }
            }
        }

        #endregion

        Upload 上传文件#region Upload 上传文件

        /**//// <summary>
        /// 上传一批文件
        /// </summary>
        /// <param name="folder">本地目录(不得以结束)</param>
        /// <param name="fileNameMask">文件名匹配字符(可以包含*和?)</param>
        public void UploadDirectory(string folder,string fileNameMask)
        ...{
            string[] strFiles = Directory.GetFiles(folder,fileNameMask);
            foreach(string strFile in strFiles)
            ...{
                //strFile是完整的文件名(包含路径)
                UploadFile(strFile);
            }
        }

        /**//// <summary>
        /// 上传一个文件
        /// </summary>
        /// <param name="fileName">本地文件名</param>
        public void UploadFile(string fileName)
        ...{
            FileStream input = new FileStream(fileName, FileMode.Open);
            this.UploadFile(input, Path.GetFileName(fileName));
            input.Close();
        }

        /**//// <summary>
        /// 上传一个文件
        /// </summary>
        /// <param name="input">流。</param>
        /// <param name="fileName">要保存为的文件名。</param>
        public void UploadFile(Stream input, string fileName)
        ...{
            // 确保已连接上服务器
            this.EnsureConnected();

            Socket socketData = CreateDataSocket();
            SendCommand("STOR " + fileName);
            if(!(this._reply.Code == 125 || this._reply.Code == 150))
            ...{
                throw new FtpClientException(this._reply.Message.Substring(4));
            }

            int iBytes = 0;
            byte[] buffer = new byte[this._blockSize];
            while ((iBytes = input.Read(buffer,0,buffer.Length)) > 0)
            ...{
                socketData.Send(buffer, iBytes, 0);
            }
            if(socketData.Connected)
            ...{
                socketData.Close();
            }
            if(!(this._reply.Code == 226 || this._reply.Code == 250))
            ...{
                ReadReply();
                if(!(this._reply.Code == 226 || this._reply.Code == 250))
                ...{
                    throw new FtpClientException(this._reply.Message.Substring(4));
                }
            }
        }

        #endregion

        MakeDirectory 创建目录#region MakeDirectory 创建目录

        /**//// <summary>
        /// 创建目录
        /// </summary>
        /// <param name="directory">目录名</param>
        public void MakeDirectory(string directory)
        ...{
            // 确保已连接上服务器
            this.EnsureConnected();

            SendCommand("MKD " + directory);
            if(this._reply.Code != 257)
            {
                throw new FtpClientException(this._reply.Message.Substring(4));
            }
        }

        #endregion

        RenameDirectory 删除目录#region RenameDirectory 删除目录

        /**//// <summary>
        /// 删除目录
        /// </summary>
        /// <param name="directory">目录名</param>
        public void RenameDirectory(string directory)
        ...{
            // 确保已连接上服务器
            this.EnsureConnected();

            SendCommand("RMD " + directory);
            if(this._reply.Code != 250)
            ...{
                throw new FtpClientException(this._reply.Message.Substring(4));
            }
        }

        #endregion

        ChangeDirectory 改变当前目录#region ChangeDirectory 改变当前目录

        /**//// <summary>
        /// 改变当前目录
        /// </summary>
        /// <param name="directory">新的工作目录名</param>
        public void ChangeDirectory(string directory)
        {
            if(directory == null || directory == string.Empty || directory == ".")
            {
                return;
            }

            // 确保已连接上服务器
            this.EnsureConnected();

            SendCommand("CWD " + directory);
            if(this._reply.Code != 250)
            {
                throw new FtpClientException(this._reply.Message.Substring(4));
            }

            this._remotePath = directory;
        }

        #endregion
    }


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/libraworm/archive/2007/07/04/1678355.aspx

  评论这张
 
阅读(270)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017