封装FTP类

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

namespace FTP
 {
      /// <summary>
      /// FTP 操作类 Create by joe 20140520
      /// </summary>
      public class FTP
      {
           private string strRemoteHost;
           private int strRemotePort;
           private string strRemotePath;
           private string strRemoteUser;
           private string strRemotePass;
           private Boolean bConnected;
         
          #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 = 512;
           Byte[] buffer = new Byte[ BLOCK_SIZE];
           /// <summary>
           /// 编码方式
           /// </summary>
           Encoding ASCII = Encoding.Default;
           #endregion
         
          #region 内部函数
         
          #region 构造函数

           /// <summary>
           /// 缺省构造函数(默认端口为21)
           /// </summary>
           public FTP()
           {
                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 FTP( string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort )
           {
            strRemoteHost  = remoteHost;
            strRemotePath  = remotePath;
            strRemoteUser  = remoteUser;
            strRemotePass  = remotePass;
            strRemotePort  = remotePort;
            Connect();
           }

          /// <summary>
          /// 实例化对象类(默认端口为21)
          /// </summary>
          /// <param name="remoteHost"></param>
          /// <param name="remotePath"></param>
          /// <param name="remoteUser"></param>
          /// <param name="remotePass"></param>
           public FTP( string remoteHost, string remotePath, string remoteUser, string remotePass)
           {
            strRemoteHost  = remoteHost;
            strRemotePath  = remotePath;
            strRemoteUser  = remoteUser;
            strRemotePass  = remotePass;
            strRemotePort  = 21;
            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>传输模式</returns>
           public TransferType GetTransferType()
           {
            return trType;
           }
         
          #endregion
         
          #region 文件操作
           /// <summary>
           /// 获得文件列表
           /// </summary>
           /// <param name="strMask">文件名的匹配字符串</param>
           /// <returns></returns>
         public string[] Dir(string strMask)
           {
            // 建立链接
            if(!bConnected)
            {
             Connect();
            }
         
           //建立进行数据连接的socket
            Socket socketData = CreateDataSocket();
         
           //传送命令
            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;
             }
            }
            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;
           }

           /// <summary>
           /// 从ftp服务器上获得文件列表
           /// </summary>
           /// <param name="RequedstPath">服务器下的相对路径</param>
           /// <returns></returns>
           public  List<string> GetFile(string RequedstPath)
           {
               List<string> strs = new List<string>();
               try
               {
                   string uri = "ftp://" + strRemoteHost + ":" + strRemotePort.ToString() + "/" + RequedstPath;   //目标路径 path为服务器地址
                   FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
                   // ftp用户名和密码
                   reqFTP.Credentials = new NetworkCredential(strRemoteUser, strRemotePass);
                   reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
                   WebResponse response = reqFTP.GetResponse();
                   StreamReader reader = new StreamReader(response.GetResponseStream());//中文文件名

                   string line = reader.ReadLine();
                   while (line != null)
                   {
                       if (!line.Contains("<DIR>"))
                       {
                           string msg = line.Substring(39).Trim();
                           strs.Add(msg);
                       }
                       line = reader.ReadLine();
                   }
                   reader.Close();
                   response.Close();
                   return strs;
               }
               catch (Exception ex)
               {
                   throw new IOException("获取文件出错:" + ex.Message);
               }
           }

          /// <summary>
           /// 获取文件大小
           /// </summary>
           /// <param name="strFileName">文件名</param>
           /// <returns>文件大小</returns>
           private 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="strFolder">本地目录(不得以结束)</param>
           public void Get(string strFileNameMask,string strFolder)
           {
            if(!bConnected)
            {
             Connect();
            }
            List<string> strFiles = GetFile(strFileNameMask);
            foreach(string strFile in strFiles)
            {
             if(!strFile.Equals(""))//一般来说strFiles的最后一个元素可能是空字符串
             {
                 Get(strFileNameMask, strFile, strFolder, strFile);
             }
            }
           }
         

          /// <summary>
           /// 下载一个文件
           /// </summary>
           /// <param name="strRemoteFileName">要下载的文件名</param>
           /// <param name="strFolder">本地目录(不得以结束)</param>
           /// <param name="strLocalFileName">保存在本地时的文件名</param>
           public void Get(string strPath,string strRemoteFileName,string strFolder,string strLocalFileName)
           {
            if(!bConnected)
            {
             Connect();
            }
            SetTransferType(TransferType.Binary);
            if (strLocalFileName.Equals(""))
            {
             strLocalFileName = strRemoteFileName;
            }
            if(!File.Exists(strLocalFileName))
            {
             Stream st = File.Create(strLocalFileName);
             st.Close();
            }
            FileStream output = new FileStream(strFolder + "\" + strLocalFileName,FileMode.Create);
            Socket socketData = CreateDataSocket();
            SendCommand("RETR " + strPath + "\" + strRemoteFileName);
            if(!(iReplyCode == 150 || iReplyCode == 125
             || iReplyCode == 226 || iReplyCode == 250))
            {
             throw new IOException(strReply.Substring(4));
            }
            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(!(iReplyCode == 226 || iReplyCode == 250))
            {
             ReadReply();
             if(!(iReplyCode == 226 || iReplyCode == 250))
             {
              throw new IOException(strReply.Substring(4));
             }
            }
           }
         

          /// <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);
               int iBytes = 0;
               while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0)
               {
                   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));
                   }
               }
           }

          #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>
          /// <returns></returns>
          public bool DirIsExist(string strDirName)
          {
              try
              {
                  Uri uri = new Uri("ftp://" + strRemoteHost + ":" + strRemotePort.ToString() + "/" + strDirName + "/");
                  if (!DirectoryIsExist(uri, strRemoteUser, strRemotePass))
                  {
                      return false;
                  }
                  else
                  {
                      return true;
                  }
              }
              catch (Exception)
              {
                  return false;
              }
          }

          /// <summary>
          /// 从ftp服务器上获得文件夹列表
          /// </summary>
          /// <param name="RequedstPath">服务器下的相对路径</param>
          /// <returns></returns>
          public  List<string> GetDirctory(string RequedstPath)
          {
              List<string> strs = new List<string>();
              try
              {
                  string uri = "ftp://" + strRemoteHost + ":" + strRemotePort.ToString() + "/" + RequedstPath;   //目标路径 path为服务器地址
                  FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
                  // ftp用户名和密码
                  reqFTP.Credentials = new NetworkCredential(strRemoteUser, strRemotePass);
                  reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
                  WebResponse response = reqFTP.GetResponse();
                  StreamReader reader = new StreamReader(response.GetResponseStream());//中文文件名

                  string line = reader.ReadLine();
                  while (line != null)
                  {
                      if (line.Contains("<DIR>"))
                      {
                          string msg = line.Substring(line.LastIndexOf("<DIR>") + 5).Trim();
                          strs.Add(msg);
                      }
                      line = reader.ReadLine();
                  }
                  reader.Close();
                  response.Close();
                  return strs;
              }
              catch (Exception ex)
              {
                  throw new IOException("获取目录出错:" + ex.Message);
              }
              return strs;
          }

          /// <summary>
          /// 判断目录是否存在
          /// </summary>
          /// <param name="pFtpServerIP"></param>
          /// <returns></returns>
          private  bool DirectoryIsExist(Uri pFtpServerIP, string strRemoteUser, string strRemotePass)
          {
              string[] value = GetFileList(pFtpServerIP, strRemoteUser, strRemotePass);
              if (value == null)
              {
                  return false;
              }
              else
              {
                  return true;
              }
          }

          /// <summary>
          ///  获取该目录以及目录下所有的文件
          /// </summary>
          /// <param name="pFtpServerIP"></param>
          /// <returns></returns>
          public  string[] GetFileList(Uri pFtpServerIP, string strRemoteUser, string strRemotePass)
          {
              StringBuilder result = new StringBuilder();
              try
              {
                  FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(pFtpServerIP);
                  reqFTP.UseBinary = true;
                  reqFTP.Credentials = new NetworkCredential(strRemoteUser, strRemotePass);
                  reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

                  WebResponse response = reqFTP.GetResponse();
                  StreamReader reader = new StreamReader(response.GetResponseStream());
                  string line = reader.ReadLine();
                  if (string.IsNullOrEmpty(line))
                  {
                      reader.Close();
                      response.Close();
                      return null;
                  }
                  else
                  {
                      while (line != null)
                      {
                          result.Append(line);
                          result.Append("
");
                          line = reader.ReadLine();
                      }
                      reader.Close();
                      response.Close();
                      return result.ToString().Split('
');
                  }
              }
              catch
              {
                  return null;
              }
          }


           /// <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;
           }

           #endregion

           /// <summary>
           /// 将一行应答字符串记录在strReply和strMsg
           /// 应答码记录在iReplyCode
           /// </summary>
           private void ReadReply()
           {
               strMsg = "";
               strReply = ReadLine();
               iReplyCode = Int32.Parse(strReply.Substring(0, 3));
           }

           /// <summary>
           /// 建立进行数据连接的socket
           /// </summary>
           /// <returns>数据连接socket</returns>
           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>包含应答码的字符串行</returns>
           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 = { '
' };
               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
    }
}

作者:Joe.Fan
         
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/fanxingthink/p/4176145.html