c# ftp类[转]

it2022-05-09  34

 

using  System; using  System.Net; using  System.IO; using  System.Text; using  System.Net.Sockets; ///   <summary> ///  FTPClient 的摘要说明。 ///   </summary> public   class  FTPClient{      #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 ){   strRemoteHost  =  remoteHost;   strRemotePath  =  remotePath;   strRemoteUser  =  remoteUser;   strRemotePass  =  remotePass;   strRemotePort  =  remotePort;   Connect();} #endregion        #region  登陆 ///   <summary> ///  FTP服务器IP地址 ///   </summary> private   string  strRemoteHost; public   string  RemoteHost{    get    {     return  strRemoteHost;   }    set    {    strRemoteHost  =  value;   }} ///   <summary> ///  FTP服务器端口 ///   </summary> private   int  strRemotePort; public   int  RemotePort{    get    {     return  strRemotePort;   }    set    {    strRemotePort  =  value;   }} ///   <summary> ///  当前服务器目录 ///   </summary> private   string  strRemotePath; public   string  RemotePath{    get    {     return  strRemotePath;   }    set    {    strRemotePath  =  value;   }} ///   <summary> ///  登录用户账号 ///   </summary> private   string  strRemoteUser; public   string  RemoteUser{    set    {    strRemoteUser  =  value;   }} ///   <summary> ///  用户登录密码 ///   </summary> private   string  strRemotePass; public   string  RemotePass{    set    {    strRemotePass  =  value;   }}  ///   <summary> ///  是否登录 ///   </summary> private  Boolean bConnected; 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> ///  传输模式:二进制类型、ASCII类型 ///   </summary> public   enum  TransferType {Binary,ASCII};  ///   <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  =  { ' \n ' };    string [] strsFileList  =  strMsg.Split(seperator);   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> 文件大小 </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();   }    string [] strFiles  =  Dir(strFileNameMask);    foreach ( string  strFile  in  strFiles)   {     if ( ! strFile.Equals( "" )) // 一般来说strFiles的最后一个元素可能是空字符串     {     Get(strFile,strFolder,strFile);    }   }}       ///   <summary> ///  下载一个文件 ///   </summary> ///   <param name="strRemoteFileName"> 要下载的文件名 </param> ///   <param name="strFolder"> 本地目录(不得以\结束) </param> ///   <param name="strLocalFileName"> 保存在本地时的文件名 </param> public   void  Get( 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  "   +  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> 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        #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> ///  接收和发送数据的缓冲区 ///   </summary> private   static   int  BLOCK_SIZE  =   512 ;Byte[] buffer  =   new  Byte[BLOCK_SIZE]; ///   <summary> ///  编码方式 ///   </summary> Encoding ASCII  =  Encoding.ASCII; #endregion        #region  内部函数 ///   <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  =  { ' \n ' };    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 =             //  Encoding.ASCII.GetBytes((strCommand + "\r\n").ToCharArray());              byte [] cmdBytes  =  Encoding.GetEncoding( " gb2312 " ).GetBytes((strCommand  +   " \r\n " ).ToCharArray());            socketControl.Send(cmdBytes, cmdBytes.Length,  0 );            ReadReply();}      #endregion   }

转载于:https://www.cnblogs.com/tuyile006/archive/2009/02/23/1396524.html

相关资源:c# FTP 服务端

最新回复(0)