FTP操作类

using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace clsFTP1
{
    public class clsFTP
    {
        #region "Class Variable Declarations"
        private string m_sRemoteHost, m_sRemotePath, m_sRemoteUser;
        private string m_sRemotePassword, m_sMessk;
        private int m_iRemotePort, m_iBytes;
        private Socket m_objClientSocket;
        private Int32 m_iRetValue;
        private bool m_bLoggedIn;
        private string m_sMes, m_sReply;
        //设置用户来对FTP服务器读取和写入数据的数据包的大小
        //对下列具体大小
        public const int BLOCK_SIZE = 512;
        private byte[] m_aBuffer= new byte[BLOCK_SIZE];
        private Encoding ASCII = Encoding.ASCII;
        public bool flag_bool;
        //普通变量定义
        private string m_sMessageString;
        #endregion

        #region "Class Constructors"
        //Main类构造器
        public clsFTP()
        {
            m_sRemoteHost = "localhost";
            m_sRemotePath = ".";
            m_sRemoteUser = "anonymous";
            m_sRemotePassword = "";
            m_sMessageString = "";
            m_iRemotePort = 21;
            m_bLoggedIn = false;
        }
        //参数化的构造器
        public clsFTP(string sRemoteHost,string sRemotePath,string sRemoteUser,string sRemotePassword,int iRemotePort)
        {
            m_sRemoteHost = sRemoteHost;
            m_sRemotePath = sRemotePath;
            m_sRemoteUser = sRemoteUser;
            m_sRemotePassword = sRemotePassword;
            m_sMessageString = "";
            m_iRemotePort = 21;
            m_bLoggedIn = false;
        }
        #endregion

        #region "Public Properties"
        //设置或得到你想链接的FTP服务器的名称
        public string RemoteHostFTPServer
        {
            //得到FTP服务器的名称
            get
            {
                return m_sRemoteHost;
            }
        }
        //设置或得到你想链接的FTP服务器的FTP端口
        public int RemotePort
        {
            //得到FTP端口号
            get
            {
                return m_iRemotePort;
            }
            set
            {
                m_iRemotePort = value;
            }
        }
        //设置或得到你想链接的FTP服务器的远程路径
        public string RemotePath
        {
            //得到的远程路径
            get
            {
                return m_sRemotePath;
            }
            set
            {
                m_sRemotePath = value;
            }
        }
        //设置你想链接的远程FTP服务器的密码
        public string RemotePassword
        {
            get
            {
                return m_sRemotePassword;
            }
            set
            {
                m_sRemotePassword = value;
            }
        }
        //设置或得到你想链接远程的FTP服务器的用户
        public string RemoteUser
        {
            get
            {
                return m_sRemoteUser;
            }
            set
            {
                m_sRemoteUser = value;
            }
        }
        //设置messagestring类
        public string MessageString
        {
            get
            {
                return m_sMessageString;
            }
            set
            {
                m_sMessageString = value;
            }
        }

        #endregion

        #region "Public Functions"
        //从文件系统中返回一个文件列表。在string()函数中返回文件。
        public string[] GetFileList(string sMask)
        {
            Socket cSocket;
            Int32 bytes;
            Char seperator = ControlChars.Lf;
            string[] mess;
            m_sMes = "";
            //检查你是否登录到FTP服务器上
            if(!m_bLoggedIn)
            {
                Login();
            }
            cSocket = CreateDataSocket();
            //发送FTP命令
            SendCommand("NLST " + sMask);
            if(!(m_iRetValue == 150 || m_iRetValue == 125))
            {
                MessageString = m_sReply;
                throw new IOException(m_sReply.Substring(4));
            }
            m_sMes = "";
            while (true)
            {
                Array.Clear(m_aBuffer, 0, m_aBuffer.Length);
                bytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0);
                m_sMes += ASCII.GetString(m_aBuffer, 0, bytes);
                if (bytes < m_aBuffer.Length)
                    break;
            }
            mess = m_sMes.Split(seperator);
            cSocket.Close();
            ReadReply();
            if(m_iRetValue != 226)
            {
                MessageString = m_sReply;
                throw new IOException(m_sReply.Substring(4));
            }
            return mess;
        }

        //得到FTP服务器上的文件大小
        public long GetFileSize(string sFileName)
        {
            long size;
            if (!m_bLoggedIn)
                Login();
            //发送一个FTP命令
            SendCommand("SIZE " + sFileName);
            size = 0;
            if (m_iRetValue == 213)
            {
                size = Int64.Parse(m_sReply.Substring(4));
            }                
            else
            {
                MessageString = m_sReply;
                throw new IOException(m_sReply.Substring(4));
            }
            return size;
        }

        //登录FTP服务器
        private bool Login()
        {
            m_objClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ep = new IPEndPoint(Dns.Resolve(m_sRemoteHost).AddressList[0], m_iRemotePort);
            try
            {
                m_objClientSocket.Connect(ep);
            }
            catch(Exception ex)
            {
                MessageString = m_sReply;
                throw new IOException("Cannot connect to the remote server");
            }
            ReadReply();
            if (m_iRetValue != 220)
            {
                CloseConnection();
                MessageString = m_sReply;
                throw new IOException(m_sReply.Substring(4));
            }
            //为了发送一个对服务器的用户登录ID,发送一个FTP命令
            SendCommand("USER " + m_sRemoteUser);
            if(!(m_iRetValue == 331 || m_iRetValue == 230))
            {
                Cleanup();
                MessageString = m_sReply;
                throw new IOException(m_sReply.Substring(4));
            }
            if(m_iRetValue!=230)
            {
                //为了发送一个对服务器的用户密码,发送一个FTP命令
                SendCommand("PASS " + m_sRemotePassword);
                if(!(m_iRetValue == 230 || m_iRetValue == 202))
                {
                    Cleanup();
                    MessageString = m_sReply;
                    throw new IOException(m_sReply.Substring(4));
                }
            }
            m_bLoggedIn = true;
            //为了改变映射的远程服务器的文件夹的目录,调用用户定义的ChangeDirectory函数
            ChangeDirectory(m_sRemotePath);
            //返回最终结果
            return m_bLoggedIn;
        }

        //如果模式值为真,对下载设置为二进制模式。否则,设置为ASCII模式
        public void SetBinaryMode(bool bMode)
        {
            if (bMode)
                //发送FTP命令,设置为二进制模式
                //(TYPE是一种用作说明请求类型的FTP命令.)
                SendCommand("TYPE I");
            else
            {
                //发送FTP命令,设置ASCII模式。
                //(TYPE是一种用作说明请求类型的FTP命令。)
                SendCommand("TYPE A");
            }
            if (m_iRetValue != 200)
            {
                MessageString = m_sReply;
                throw new IOException(m_sReply.Substring(4));
            }              
        }

        //向一个配置好的本地文件夹下载一个远程文件。保持文件名一样。
        public void DownloadFile(string sFileName,bool bResume)
        {
            DownloadFile(sFileName, "", bResume);
        }

         //地文件名下载一个远程文件。你必须包含一个路径。
        //本地文件名将会创建或者将会被重写,但是路径必须存在。
        public void DownloadFile(string sFileName,string sLocalFileName)
        {
            DownloadFile(sFileName, sLocalFileName, false);
        }
        //对一个本地文件名下载一个远程文件。你必须包含一个路径。设置恢复标志。本地文件名将会被创建或被重写,但是本地路径必须存在。
        public void DownloadFile(string sFileName, string sLocalFileName,bool bResume)
        {
            Stream st;
            FileStream output;
            Socket cSocket;
            long offset, npos;
            if (!m_bLoggedIn)
                Login();
            SetBinaryMode(true);
            if(sLocalFileName.Equals(""))
            {
                sLocalFileName = sFileName;
            }
            if (!(File.Exists(sLocalFileName)))
            {
                st = File.Create(sLocalFileName);
                st.Close();
            }
            output = new FileStream(sLocalFileName, FileMode.Open);
            cSocket = CreateDataSocket();
            offset = 0;
            if (bResume)
            {
                offset = output.Length;
                if (offset > 0)
                {
                    //发送一个FTP命令重新启动
                    SendCommand("REST " + offset);
                    if (m_iRetValue != 350)
                        offset = 0;
                }
                if (offset > 0)
                    npos = output.Seek(offset, SeekOrigin.Begin);
            }
            //发送一个FTP命令重新找到一个文件。  
            SendCommand("RETR " + sFileName);
            if(!(m_iRetValue == 150 || m_iRetValue == 125))
            {
                MessageString = m_sReply;
                throw new IOException(m_sReply.Substring(4));
            }
            while(true)
            {
                Array.Clear(m_aBuffer, 0, m_aBuffer.Length);
                m_iBytes = cSocket.Receive(m_aBuffer, m_aBuffer.Length, 0);
                output.Write(m_aBuffer, 0, m_iBytes);
                if (m_iBytes <= 0)
                    break;
            }
            output.Close();
            if (cSocket.Connected)
                cSocket.Close();
            ReadReply();
            if(!(m_iRetValue == 226 || m_iRetValue == 250))
            {
                MessageString = m_sReply;
                throw new IOException(m_sReply.Substring(4));
            }
        }

        //这是一个从你的本地硬盘上向你的FTP文件夹中上载文件的函数
        public void UploadFile(string sFileName)
        {
            UploadFile(sFileName, false);
        }

        //这是一个从你的本地硬盘上向你的FTP网页上上载的函数和设置恢复标志
        public void UploadFile(string sFileName,bool bResume)
        {
            Socket cSocket;
            long offset;
            FileStream input;
            bool bFileNotFound;
            if (!m_bLoggedIn)
                Login();
            cSocket = CreateDataSocket();
            offset = 0;
            if(bResume)
            {
                try
                {
                    SetBinaryMode(true);
                    offset = GetFileSize(sFileName);
                }
                catch(Exception ex)
                {
                    offset = 0;
                }
            }
            if(offset>0)
            {
                SendCommand("REST " + offset);
                if (m_iRetValue != 350)
                    //远程服务器可能不支持恢复。
                    offset = 0;
            }
            //发送一个FTP命令,存储一个文件。
            SendCommand("STOR " + Path.GetFileName(sFileName));
            if(!(m_iRetValue == 125 || m_iRetValue == 150))
            {
                MessageString = m_sReply;
                throw new IOException(m_sReply.Substring(4));
            }
            //在上载之前,检查文件是否存在。
            bFileNotFound = false;
            if(File.Exists(sFileName))
            {
                //打开输入流读取源文件
                input = new FileStream(sFileName, FileMode.Open);
                if (offset != 0)
                    input.Seek(offset, SeekOrigin.Begin);
                //上载这个文件
                m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length);
                while (m_iBytes > 0)
                {
                    cSocket.Send(m_aBuffer, m_iBytes, 0);
                    m_iBytes = input.Read(m_aBuffer, 0, m_aBuffer.Length);
                }
                input.Close();
            }
            else
            {
                bFileNotFound = true;
            }
            if (cSocket.Connected)
                cSocket.Close();
            //如果找不到文件,检查返回值
            if(bFileNotFound)
            {
                MessageString = m_sReply;
                throw new IOException("The file: " + sFileName + " was not found. " +
           "Cannot upload the file to the FTP site");
            }
            ReadReply();
            if(!(m_iRetValue == 226 || m_iRetValue == 250))
            {
                MessageString = m_sReply;
                throw new IOException(m_sReply.Substring(4));
            }
        }
        //从远程FTP服务器上删除一个文件。
        public bool DeleteFile(string sFileName)
        {
            bool bResult;
            bResult = true;
            if (!m_bLoggedIn)
                Login();
            //发送一个FTP命令,删除一个文件。
            SendCommand("DELE " + sFileName);
            if (m_iRetValue != 250)
            {
                bResult = false;
                MessageString = m_sReply;
            }
            // 返回最终结果  
            return bResult;
        }
        //在远程FTP服务器上重命名一个文件
        public bool RenameFile(string sOldFileName,string sNewFileName)
        {
            bool bResult;
            bResult = true;
            if (!m_bLoggedIn)
                Login();
            //发送一个FTP命令,对一个文件重命名
            SendCommand("RNFR " + sOldFileName);
            if(m_iRetValue!=350)
            {
                MessageString = m_sReply;
                throw new IOException(m_sReply.Substring(4));
            }
            //发送一个FTP命令,对一个文件更改为新名称
            //如果新的文件名存在,会被覆盖。
            SendCommand("RNTO " + sNewFileName);
            if(m_iRetValue != 250)
            {
                MessageString = m_sReply;
                throw new IOException(m_sReply.Substring(4));
            }
            return bResult;
        }
        //这是一个在远程服务器上创建目录的函数
        public bool CreateDirectory(string sDirName)
        {
            bool bResult;
            bResult = true;
            if (!m_bLoggedIn)
                Login();
            //发送一个FTP命令,在FTP服务器上制作一个目录
            SendCommand("MKD " + sDirName);
            if(m_iRetValue != 257)
            {
                bResult = false;
                MessageString = m_sReply;
            }
            //返回最终结果
            return bResult;
        }

        //这是一个在远程FTP服务器上删除目录的函数
        public bool RemoveDirectory(string sDirName)
        {
            bool bResult;
            bResult = true;
            //检查是否已登录FTP服务器
            if (!m_bLoggedIn)
                Login();
            // 发送一个FTP命令,删除在FTP服务器上的目录
            SendCommand("RMD " + sDirName);
            if (m_iRetValue != 250)
            {
                bResult = false;
                MessageString = m_sReply;
            }
            //返回最终结果
            return bResult;
        }

        //这是一个用来在远程FTP服务器上改变当前工作目录的函数。
        public bool ChangeDirectory(string sDirName)
        {
            bool bResult;
            bResult = true;
            // 检查你是否在根目录
            if ((sDirName.Equals(".")))
                return bResult;
            // 检查是否已登录FTP服务器
            if ((!(m_bLoggedIn)))
                Login();
            // 发送FTP命令,改变在FTP服务器上的目录。
            SendCommand("CWD " + sDirName);
            if ((m_iRetValue != 250))
            {
                bResult = false;
                MessageString = m_sReply;
            }
            this.m_sRemotePath = sDirName;
            // 返回最终结果
            return bResult;
        }
        //关闭远程服务器的FTP链接
        public void CloseConnection()
        {
            if (!(m_objClientSocket == null))
                //发送一个FTP命令,结束FTP服务系统。
                SendCommand("QUIT");
            Cleanup();
        }
        #endregion

        #region "Private Functions"
        //从FTP服务器得到回应。
        private void ReadReply()
        {
            m_sMes = "";
            m_sReply = ReadLine();
            m_iRetValue = Int32.Parse(m_sReply.Substring(0, 3));
        }
        //清除一些变量
        private void Cleanup()
        {
            if(!(m_objClientSocket==null))
            {
                m_objClientSocket.Close();
                m_objClientSocket = null;
            }
            m_bLoggedIn = false;
        }

        //从FTP服务器读取一行。
        private string ReadLine(bool bClearMes=false)
        {
            Char seperator = ControlChars.Lf;
            string[] mess;
            if (bClearMes)
                m_sMes = "";
            while(true)
            {
                m_aBuffer.Clear(m_aBuffer, 0, BLOCK_SIZE);
                m_iBytes = m_objClientSocket.Receive(m_aBuffer, m_aBuffer.Length, 0);
                m_sMes += ASCII.GetString(m_aBuffer, 0, m_iBytes);
                if (m_iBytes < m_aBuffer.Length)
                    break;
            }
            mess = m_sMes.Split(seperator);
            if (m_sMes.Length > 2)
                m_sMes = mess[mess.Length - 2];
            else
                m_sMes = mess[0];
            if(!(m_sMes.Substring(3, 1).Equals(" ")))
                return ReadLine(true);
            return m_sMes;
        }

        //这是一个你想链接的FTP服务器用于发送命令的函数。
        private void SendCommand(string sCommand)
        {
            sCommand = sCommand + ControlChars.CrLf;
            byte[] cmdbytes = ASCII.GetBytes(sCommand);
            m_objClientSocket.Send(cmdbytes, cmdbytes.Length, 0);
            ReadReply();
        }

        //创建一个数据包
        private Socket CreateDataSocket()
        {
            Int32 index1, index2, len;
            Int32 partCount, i, port;
            string ipData, buf, ipAddress;
            Int32[] parts = new Int32[6];
            char ch;
            Socket s;
            IPEndPoint ep;
            //发送一个FTP命令,用于被动数据链接
            SendCommand("PASV");
            if (m_iRetValue != 227)
            {
                MessageString = m_sReply;
                throw new IOException(m_sReply.Substring(4));
            }
            index1 = m_sReply.IndexOf("(");
            index2 = m_sReply.IndexOf(")");
            ipData = m_sReply.Substring(index1 + 1, index2 - index1 - 1);
            len = ipData.Length;
            partCount = 0;
            buf = "";
            for (i = 0; i <= (len - 1) && partCount <= 6; i++)
            {
                ch = Char.Parse(ipData.Substring(i, 1));
                if (Char.IsDigit(ch))
                    buf += ch;

                else if (ch != ',')
                {
                    MessageString = m_sReply;
                    throw new IOException("Malformed PASV reply: " + m_sReply);
                }
                if ((ch == ',') || (i + 1 == len))
                {
                    try
                    {
                        parts[partCount] = Int32.Parse(buf);
                        partCount += 1;
                        buf = "";
                    }
                    catch(Exception ex)
                    {
                        MessageString = m_sReply;
                        throw new IOException("Malformed PASV reply: " + m_sReply);
                    }
                }
            }
            ipAddress = parts[0] + "." + parts[1] + "." + parts[2] + "." + parts[3];
            //在Visual Basic .Net 2002中进行调用。你想移动8位。在Visual Basic .NET 2002中,你必须将此数乘2的8次方。
            //端口=parts(4)*(2^8)
            //进行这个调用,并且用Visual Basic .NET 2003解释当前行。
            port = parts[4] << 8;
            //确定数据端口数
            port = port + parts[5];
            s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            ep = new IPEndPoint(Dns.Resolve(ipAddress).AddressList[0], port);
            try
            {
                s.Connect(ep);
            }
            catch(Exception ex)
            {
                MessageString = m_sReply;
                throw new IOException("Cannot connect to remote server.");
                //如果你不能链接到特定的FTP服务器,也就是说,将其布尔值设置为false。
                flag_bool = false;
            }
            //如果你能够链接到特定的FTP服务器,将布尔值设置为true。
            flag_bool = true;
            return s;
        }
        #endregion
    }
}

  

posted @ 2019-12-21 20:13  惊风雨  阅读(163)  评论(0)    收藏  举报