.net 访问FTP里内容 ,FTPFactory类

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

namespace FtpLib
{

 public class FTPFactory
 {

  private string remoteHost,remotePath,remoteUser,remotePass,mes;
  private int remotePort,bytes;
  private Socket clientSocket;

  private int retValue;
  private Boolean debug;
  private Boolean logined;
  private string reply;

  private static int BLOCK_SIZE = 512;

  Byte[] buffer = new Byte[BLOCK_SIZE];
  Encoding ASCII = Encoding.ASCII;

  /// <summary>
  /// 构造函数
  /// </summary>
  /// <param name="remHost">远程主机地址</param>
  /// <param name="remPort">远程端口</param>
  /// <param name="remPath">远程路径</param>
  /// <param name="remUser">远程用户</param>
  /// <param name="remPass">远程用户密码</param>
  /// <param name="debugFlag">调试标志</param>
  public FTPFactory(string remHost, int remPort, string remPath, string remUser, string remPass, bool debugFlag)
  {
   remoteHost = remHost;
   remotePort = remPort;
   remotePath = remPath;
   remoteUser = remUser;
   remotePass = remPass;
   debug = debugFlag;
   logined = false;
  }

  /// <summary>
  /// 远程主机地址
  /// </summary>
  public string RemoteHost
  {
   get
   {
    return this.remoteHost;
   }
   set
   {
    this.remoteHost = value;
   }
  }

  /// <summary>
  /// 远程端口
  /// </summary>
  public int RemotePort
  {
   get
   {
    return this.remotePort;
   }
   set
   {
    this.remotePort = value;
   }
  }

  /// <summary>
  /// 远程主机路径
  /// </summary>
  public string RemotePath
  {
   get
   {
    return this.remotePath;
   }
   set
   {
    this.remotePath = value;
   }
  }

  /// <summary>
  /// 远程用户名
  /// </summary>
  public string RemoteUser
  {
   get
   {
    return this.remoteUser;
   }
   set
   {
    this.remoteUser = value;
   }
  }

  /// <summary>
  /// 远程用户密码
  /// </summary>
  public string RemotePass
  {
   set
   {
    this.remotePass = value;
   }
  }

  /// <summary>
  /// 获得目录列表
  /// </summary>
  /// <param name="mask">目录</param>
  /// <returns>目录集合</returns>
  public string[] getDirList(string mask)
  {
   if(!logined)
   {
    login();
   }

   Socket cSocket = createDataSocket();
   sendCommand("LIST " + mask);

   if(!(retValue == 150 || retValue == 125 || retValue == 226))
   {
    throw new IOException(reply.Substring(4));
   }

   mes = "";

   while(true)
   {

    int bytes = cSocket.Receive(buffer, buffer.Length, 0);
    mes += ASCII.GetString(buffer, 0, bytes);

    if(bytes < buffer.Length)
    {
     break;
    }
   }

   char[] seperator = {'\n'};
   string[] mess = mes.Split(seperator);

   cSocket.Close();

   ArrayList list = new ArrayList();

   foreach(string m in mess)
   {
    if (m.StartsWith("d") && !m.EndsWith(".\r") && !m.EndsWith("..\r"))
    {
     if (!"".Equals(this.getDirName(m)))
      list.Add(this.getDirName(m));
    }
   }

   string[] dirs = new string[list.Count];
   
   for(int i=0;i<dirs.Length;i++)
   {
    dirs[i] = list[i].ToString();
   }


   readReply();

   if(retValue != 226)
   {
    throw new IOException(reply.Substring(4));
   }
   return dirs;
  }

  /// <summary>
  /// 获得文件列表
  /// </summary>
  /// <param name="mask">目录</param>
  /// <returns>文件列表</returns>
  public string[] getFileList(string mask)
  {
   if(!logined)
   {
    login();
   }

   Socket cSocket = createDataSocket();
   sendCommand("NLST " + mask);

   if (retValue == 550)
    return new string[0];

   if(!(retValue == 150 || retValue == 125 || retValue == 226))
   {
    throw new IOException(reply.Substring(4));
   }

   mes = "";

   while(true)
   {

    int bytes = cSocket.Receive(buffer, buffer.Length, 0);
    mes += ASCII.GetString(buffer, 0, bytes);

    if(bytes < buffer.Length)
    {
     break;
    }
   }

   char[] seperator = {'\n'};
   string[] mess = mes.Split(seperator);

   cSocket.Close();
   
   ArrayList list = new ArrayList();

   foreach(string m in mess)
   {
    if (!"".Equals(m.Replace("\r","")))
     list.Add(m.Replace("\r",""));
   }

   string[] files = new string[list.Count];
   
   for(int i=0;i<files.Length;i++)
   {
    files[i] = list[i].ToString();
   }

   readReply();

   if(retValue != 226)
   {
    throw new IOException(reply.Substring(4));
   }
   return files;

  }

  /// <summary>
  /// 获得文件大小
  /// </summary>
  /// <param name="fileName">文件名</param>
  /// <returns></returns>
  public long getFileSize(string fileName)
  {

   if(!logined)
   {
    login();
   }

   sendCommand("SIZE " + fileName);
   long size=0;

   if(retValue == 213)
   {
    size = Int64.Parse(reply.Substring(4));
   }
   else
   {
    throw new IOException(reply.Substring(4));
   }

   return size;

  }

  /// <summary>
  /// 登录
  /// </summary>
  public void login()
  {

   clientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
   IPEndPoint ep = new IPEndPoint(Dns.Resolve(remoteHost).AddressList[0], remotePort);

   try
   {
    clientSocket.Connect(ep);
   }
   catch(Exception)
   {
    throw new IOException("Couldn't connect to remote server");
   }

   readReply();
   if(retValue != 220)
   {
    close();
    throw new IOException(reply.Substring(4));
   }
   if(debug)
    Console.WriteLine("USER "+remoteUser);

   sendCommand("USER "+remoteUser);

   if( !(retValue == 331 || retValue == 230) )
   {
    cleanup();
    throw new IOException(reply.Substring(4));
   }

   if( retValue != 230 )
   {
    if(debug)
     Console.WriteLine("PASS xxx");

    sendCommand("PASS "+remotePass);
    if( !(retValue == 230 || retValue == 202) )
    {
     cleanup();
     throw new IOException(reply.Substring(4));
    }
   }

   logined = true;
   Console.WriteLine("Connected to "+remoteHost);

   chdir(remotePath);

  }


  /// <summary>
  /// 设置模式
  /// </summary>
  /// <param name="mode">模式</param>
  /// <remarks>mode为True:Binary模式, mode为False:Ascii模式</remarks>
  public void setBinaryMode(Boolean mode)
  {
   if(mode)
   {
    sendCommand("TYPE I");
   }
   else
   {
    sendCommand("TYPE A");
   }
   if (retValue != 200)
   {
    throw new IOException(reply.Substring(4));
   }
  }


  /// <summary>
  /// 下载文件
  /// </summary>
  /// <param name="remFileName">远程文件名</param>
  public void download(string remFileName)
  {
   download(remFileName,"",false);
  }

  /// <summary>
  /// 下载文件
  /// </summary>
  /// <param name="remFileName">远程文件名</param>
  /// <param name="resume">摘要标志</param>
  public void download(string remFileName,Boolean resume)
  {
   download(remFileName,"",resume);
  }

  /// <summary>
  /// 下载文件
  /// </summary>
  /// <param name="remFileName">远程文件名</param>
  /// <param name="locFileName">本地文件名</param>
  /// <remarks>本地文件被创建或者覆盖,但是目录必须存在.</remarks>
  public void download(string remFileName,string locFileName)
  {
   download(remFileName,locFileName,false);
  }

  /// <summary>
  /// 下载文件
  /// </summary>
  /// <param name="remFileName">远程文件名</param>
  /// <param name="locFileName">本地文件名</param>
  /// <param name="resume">摘要标志</param>
  /// <remarks>本地文件被创建或者覆盖,但是目录必须存在.</remarks>
  public void download(string remFileName,string locFileName,Boolean resume)
  {
   if(!logined)
   {
    login();
   }

   setBinaryMode(true);

   Console.WriteLine("Downloading file "+remFileName+" from "+remoteHost + "/"+remotePath);

   if (locFileName.Equals(""))
   {
    locFileName = remFileName;
   }

   if(!File.Exists(locFileName))
   {
    Stream st = File.Create(locFileName);
    st.Close();
   }

   FileStream output = new 
    FileStream(locFileName,FileMode.Open);

   Socket cSocket = createDataSocket();

   long offset = 0;

   if(resume)
   {

    offset = output.Length;

    if(offset > 0 )
    {
     sendCommand("REST "+offset);
     if(retValue != 350)
     {
      //throw new IOException(reply.Substring(4));
      //Some servers may not support resuming.
      offset = 0;
     }
    }

    if(offset > 0)
    {
     if(debug)
     {
      Console.WriteLine("seeking to " + offset);
     }
     long npos = output.Seek(offset,SeekOrigin.Begin);
     Console.WriteLine("new pos="+npos);
    }
   }

   sendCommand("RETR " + remFileName);

   if(!(retValue == 150 || retValue == 125 || retValue == 226))
   {
    throw new IOException(reply.Substring(4));
   }

   while(true)
   {

    bytes = cSocket.Receive(buffer, buffer.Length, 0);
    output.Write(buffer,0,bytes);

    if(bytes <= 0)
    {
     break;
    }
   }

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

   Console.WriteLine("");

   readReply();

   if( !(retValue == 226 || retValue == 250) )
   {
    throw new IOException(reply.Substring(4));
   }

  }

  /// <summary>
  /// 上传文件
  /// </summary>
  /// <param name="fileName">文件名</param>
  public void upload(string fileName)
  {
   upload(fileName,false);
  } 

  /// <summary>
  /// 上传文件
  /// </summary>
  /// <param name="fileName">文件名</param>
  /// <param name="resume">摘要标志</param>
  public void upload(string fileName,Boolean resume)
  {

   if(!logined)
   {
    login();
   }

   Socket cSocket = createDataSocket();
   long offset=0;

   if(resume)
   {

    try
    {

     setBinaryMode(true);
     offset = getFileSize(fileName);

    }
    catch(Exception)
    {
     offset = 0;
    }
   }

   if(offset > 0 )
   {
    sendCommand("REST " + offset);
    if(retValue != 350)
    {
     //throw new IOException(reply.Substring(4));
     //Remote server may not support resuming.
     offset = 0;
    }
   }

   sendCommand("STOR "+Path.GetFileName(fileName));

   if( !(retValue == 125 || retValue == 150) )
   {
    throw new IOException(reply.Substring(4));
   }

   // open input stream to read source file
   FileStream input = new 
    FileStream(fileName,FileMode.Open);

   if(offset != 0)
   {

    if(debug)
    {
     Console.WriteLine("seeking to " + offset);
    }
    input.Seek(offset,SeekOrigin.Begin);
   }

   Console.WriteLine("Uploading file "+fileName+" to "+remotePath);

   while ((bytes = input.Read(buffer,0,buffer.Length)) > 0)
   {

    cSocket.Send(buffer, bytes, 0);

   }
   input.Close();

   Console.WriteLine("");

   if (cSocket.Connected)
   {
    cSocket.Close();
   }

   readReply();
   if( !(retValue == 226 || retValue == 250) )
   {
    throw new IOException(reply.Substring(4));
   }
  }

  /// <summary>
  /// 删除远程文件
  /// </summary>
  /// <param name="fileName">文件名</param>
  public void deleteRemoteFile(string fileName)
  {

   if(!logined)
   {
    login();
   }

   sendCommand("DELE "+fileName);

   if(retValue != 250)
   {
    throw new IOException(reply.Substring(4));
   }

  }

  /// <summary>
  /// 重命名远程文件
  /// </summary>
  /// <param name="oldFileName">原始文件名</param>
  /// <param name="newFileName">新文件名</param>
  public void renameRemoteFile(string oldFileName,string newFileName)
  {

   if(!logined)
   {
    login();
   }

   sendCommand("RNFR "+oldFileName);

   if(retValue != 350)
   {
    throw new IOException(reply.Substring(4));
   }

   //  known problem
   //  rnto will not take care of existing file.
   //  i.e. It will overwrite if newFileName exist
   sendCommand("RNTO "+newFileName);
   if(retValue != 250)
   {
    throw new IOException(reply.Substring(4));
   }

  }

  /// <summary>
  /// 创建目录
  /// </summary>
  /// <param name="dirName">目录名</param>
  public void mkdir(string dirName)
  {

   if(!logined)
   {
    login();
   }

   sendCommand("MKD "+dirName);

   if(retValue != 250)
   {
    throw new IOException(reply.Substring(4));
   }

  }

  /// <summary>
  /// 删除目录
  /// </summary>
  /// <param name="dirName">目录名</param>
  public void rmdir(string dirName)
  {

   if(!logined)
   {
    login();
   }

   sendCommand("RMD "+dirName);

   if(retValue != 250)
   {
    throw new IOException(reply.Substring(4));
   }

  }

  /// <summary>
  /// 改变当前工作路径
  /// </summary>
  /// <param name="dirName">目录名称</param>
  public void chdir(string dirName)
  {
   if(dirName.Equals("."))
   {
    return;
   }
   if(!logined)
   {
    login();
   }

   sendCommand("CWD "+dirName);

   if(retValue != 250)
   {
    throw new IOException(reply.Substring(4));
   }

   this.remotePath = dirName;

   Console.WriteLine("Current directory is "+remotePath);

  }

  /// <summary>
  /// 关闭Ftp连接
  /// </summary>
  public void close()
  {

   if( clientSocket != null )
   {
    sendCommand("QUIT");
   }

   cleanup();
   Console.WriteLine("Closing");
  }

  /// <summary>
  /// 设置调试模式
  /// </summary>
  /// <param name="debug">调式模式</param>
  public void setDebug(Boolean debug)
  {
   this.debug = debug;
  }

  private void readReply()
  {
   mes = "";
   reply = readLine();
   retValue = Int32.Parse(reply.Substring(0,3));
  }

  private void cleanup()
  {
   if(clientSocket!=null)
   {
    clientSocket.Close();
    clientSocket = null;
   }
   logined = false;
  }

  private string readLine()
  {

   while(true)
   {
    bytes = clientSocket.Receive(buffer, buffer.Length, 0);
    mes += ASCII.GetString(buffer, 0, bytes);
    if(bytes < buffer.Length)
    {
     break;
    }
   }

   char[] seperator = {'\n'};
   string[] mess = mes.Split(seperator);

   if(mes.Length > 2)
   {
    mes = mess[mess.Length-2];
   }
   else
   {
    mes = mess[0];
   }

   if(!mes.Substring(3,1).Equals(" "))
   {
    return readLine();
   }

   if(debug)
   {
    for(int k=0;k < mess.Length-1;k++)
    {
     Console.WriteLine(mess[k]);
    }
   }
   return mes;
  }

  private void sendCommand(String command)
  {
   Byte[] cmdBytes = 
    Encoding.ASCII.GetBytes((command+"\r\n").ToCharArray());
   clientSocket.Send(cmdBytes, cmdBytes.Length, 0);
   readReply();
  }

  private Socket createDataSocket()
  {

   sendCommand("PASV");

   if(retValue != 227)
   {
    throw new IOException(reply.Substring(4));
   }

   int index1 = reply.IndexOf('(');
   int index2 = reply.IndexOf(')');
   string ipData = 
    reply.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 reply: " + 
      reply);
    }

    if (ch == ',' || i+1 == len)
    {

     try
     {
      parts[partCount++] = Int32.Parse(buf);
      buf="";
     }
     catch (Exception)
     {
      throw new IOException("Malformed PASV reply: " + 
       reply);
     }
    }
   }

   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(Dns.Resolve(ipAddress).AddressList[0], port);

   try
   {
    s.Connect(ep);
   }
   catch(Exception)
   {
    throw new IOException("Can't connect to remote server");
   }

   return s;
  }


  private string getDirName(string mess)
  {
   string dirName = string.Empty;
   Char blank = ' ';
   bool flag = false;
   int j = 0;

   Char[] chars = mess.ToCharArray();
   for(int i=0;i<chars.Length;i++)
   {
    if (!flag)
    {
     if (blank == chars[i])
      flag = true;
    }
    else
    {
     if (blank != chars[i])
     {
      flag = false;
      j ++;
     }
    }

    if (j==8)
    {
     dirName = mess.Substring(i).Replace("\r","");
     break;
    }
   }

   return dirName;
  }
 }
}

posted @ 2010-10-29 11:08  小锋神  阅读(1088)  评论(0编辑  收藏  举报