C#写的FTP类(找不到原作者了)

来源:互联网 发布:开淘宝店如何找货源 编辑:程序博客网 时间:2024/05/30 22:45
//c#上传下载ftp(支持断点续传)using System;using System.Net;using System.IO;using System.Text;using System.Net.Sockets;namespace ftpGet{/// <summary>/// FTP Client/// </summary>public class FTPClient{#region 构造函数/// <summary>/// 缺省构造函数/// </summary>public FTPClient(){strRemoteHost = "";strRemotePath = "";strRemoteUser = "";strRemotePass = "";strRemotePort = 21;bConnected = false;}/// <summary>/// 构造函数/// </summary>/// <param name="remoteHost">FTP服务器IP地址</param>/// <param name="remotePath">当前服务器目录</param>/// <param name="remoteUser">登录用户账号</param>/// <param name="remotePass">登录用户密码</param>/// <param name="remotePort">FTP服务器端口</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 emotePort    {    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;    // 切换到初始目录     if (!string.IsNullOrEmpty(strRemotePath))    {    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("LIST " + 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 += GB2312.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>    public 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的最后一个元素可能是空字符串    {    if  (strFile.LastIndexOf(".") > -1)    {    Get(strFile.Replace("\r", ""), strFolder, strFile.Replace("\r", ""));    }    }    }    }        /// <summary>    /// 下载目录    /// </summary>    /// <param name="strRemoteFileName">要下载的文件名</param>    /// <param name="strFolder">本地目录(不得以\结束)</param>    /// <param name="strLocalFileName">保存在本地时的文件名</param>    public void Get(string strRemoteFileName, string strFolder, string strLocalFileName)    {    if (strLocalFileName.StartsWith("-r"))    {    string[] infos = strLocalFileName.Split(' ');    strRemoteFileName=strLocalFileName = infos[infos.Length - 1];    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="strRemoteFileName">要下载的文件名</param>    /// <param name="strFolder">本地目录(不得以\结束)</param>    /// <param name="strLocalFileName">保存在本地时的文件名</param>    public void GetFile(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="strRemoteFileName">要下载的文件名</param>    /// <param name="strFolder">本地目录(不得以\结束)</param>    /// <param name="strLocalFileName">保存在本地时的文件名</param>    public void GetBrokenFile(string strRemoteFileName, string strFolder, string strLocalFileName,long size)    {    if (!bConnected)    {                    Connect();    }                SetTransferType(TransferType.Binary);     FileStream output = new FileStream(strFolder + "\\" + strLocalFileName, FileMode.Append);    Socket socketData = CreateDataSocket();    SendCommand("REST " + size.ToString());    SendCommand("RETR " + strRemoteFileName);    if (!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226 || iReplyCode == 250))    {    throw new IOException(strReply.Substring(4));     }    //int byteYu = (int)size % 512;    //int byteChu = (int)size / 512;    //byte[] tempBuffer = new byte[byteYu];    //for (int i = 0; i < byteChu; i++)    //{                //    socketData.Receive(buffer, buffer.Length, 0);                //}    //socketData.Receive(tempBuffer, tempBuffer.Length, 0);    //socketData.Receive(buffer, byteYu, 0);    while (true)    {    int iBytes = socketData.Receive(buffer, buffer.Length, 0);    //totalBytes += iBytes;    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>    /// 编码方式(为防止出现中文乱码采用 GB2312编码方式)    /// </summary>    Encoding GB2312 = Encoding.GetEncoding("gb2312");    #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 += GB2312.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 = GB2312.GetBytes((strCommand + "\r\n").ToCharArray());    socketControl.Send(cmdBytes, cmdBytes.Length, 0);    ReadReply();        }    #endregion    }}using System;using System.Collections.Generic;using System.Text;using System.IO;namespace ftpGet{    class Program    {static string remotingFolder = System.Configuration.ConfigurationSettings.AppSettings["remotingFolder"];  //远程ftp文件目录        static string localFolder = System.Configuration.ConfigurationSettings.AppSettings["localFolder"];  //要下载到的本地目录        static string ftpServer = System.Configuration.ConfigurationSettings.AppSettings["ftpServer"];  //ftp服务器        static string user = System.Configuration.ConfigurationSettings.AppSettings["user"];  //用户名        static string pwd = System.Configuration.ConfigurationSettings.AppSettings["pwd"];  //密码        static string port = System.Configuration.ConfigurationSettings.AppSettings["port"];  //端口        static void Main(string[] args)        {            FTPClient client = new FTPClient(ftpServer, "/", user, pwd, int.Parse(port));            client.Connect();            GetFolder("*", remotingFolder, client, CreateFolder());            client.DisConnect();            ClearFolder();            Console.WriteLine("下载完毕");            System.Threading.Thread.Sleep(3000);        }        /// <summary>        /// 在本地目录下创建一个以日期为名称的目录,我做这个ftp的主要目的是为了每天都备份        /// </summary>        /// <returns>创建的目录名</returns>        private static string CreateFolder()        {            string folder=localFolder + "\\"+DateTime.Now.ToShortDateString();            if (!Directory.Exists(folder))                Directory.CreateDirectory(folder);                        return folder;        }        /// <summary>        /// 在下载结束后清空程序目录的多余文件        /// </summary>        private static void ClearFolder()        {string folder = Environment.CurrentDirectory;            string[] dictorys = Directory.GetFiles(folder);            foreach (string dictory in dictorys)            {                FileInfo info = new FileInfo(dictory);                if (info.Length == 0)File.Delete(dictory);            }       }/// <summary>        /// 递归获取ftp文件夹的内容        /// </summary>        /// <param name="fileMark">文件标记</param>        /// <param name="path">远程路径</param>        /// <param name="client"></param>        /// <param name="folder"></param>        private static void GetFolder(string fileMark, string path, FTPClient client, string folder)        {            string[] dirs = client.Dir(path);  //获取目录下的内容            client.ChDir(path);  //改变目录            foreach (string dir in dirs)            {                string[] infos = dir.Split(' ');                string info = infos[infos.Length - 1].Replace("\r", "");                if (dir.StartsWith("d") && !string.IsNullOrEmpty(dir))  //为目录                {                    if (!info.EndsWith(".") && !info.EndsWith(".."))  //筛选出真实的目录                    {                        Directory.CreateDirectory(folder + "\\" + info);                        GetFolder(fileMark, path + "/" + info, client, folder + "\\" + info);                        client.ChDir(path);                    }}                else if (dir.StartsWith("-r"))  //为文件                {string file = folder + "\\" + info;                    if (File.Exists(file)){long remotingSize = client.GetFileSize(info);FileInfo fileInfo = new FileInfo(file);                        long localSize = fileInfo.Length;                        if (remotingSize != localSize)  //短点续传                        {                            client.GetBrokenFile(info, folder, info, localSize);}                    }                    else                    {                        client.GetFile(info, folder, info);  //下载文件                        Console.WriteLine("文件" + folder + info + "已经下载");                    }                }            }        }    }}//配置文件//< xml version="1.0" encoding="utf-8"  ><configuration>  <appSettings>    <add key="remotingFolder" value="/temp"/>    <add key="localFolder" value="c:\temp"/>    <add key="ftpServer" value="*"/>    <add key="user" value="*"/>    <add key="pwd" value="*"/>    <add key="port" value="21"/>  </appSettings></configuration>

原创粉丝点击