csharp:FTP Client Library using FtpWebRequest or Sockets

https://netftp.codeplex.com/SourceControl/latest

http://ftplib.codeplex.com/

https://www.codeproject.com/articles/18537/c-ftp-client-library

https://www.codeproject.com/Articles/31624/An-FTP-secure-client-library-for-C

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Runtime;

namespace ftpdemo
{

    /// <summary>
    /// 
    /// </summary>
    public partial class Form2 : Form
    {
        string ftpServerIP;
        string ftpUserID;
        string ftpPassword;
        /// <summary>
        /// 
        /// </summary>
        public Form2()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form2_Load(object sender, EventArgs e)
        {
            ftpServerIP = "88.88.88.88";// 
            ftpUserID = "dusystem.com";//dusystem.com
            ftpPassword = "geovindu";////
            txtServerIP.Text = ftpServerIP;
            txtUsername.Text = ftpUserID;
            txtPassword.Text = ftpPassword;
            this.Text += ftpServerIP;

            btnFTPSave.Enabled = false;
        }

        /// <summary>
        /// Method to upload the specified file to the specified FTP Server
        /// 隻能是根目錄下,要解決這個問題
        /// 上传,必须存在文件夹下。
        /// 最好是不要用中文名称文件夹或文件
        /// </summary>
        /// <param name="filename">file full name to be uploaded</param>
        private void Upload(string filename)
        {
            FileInfo fileInf = new FileInfo(filename);
            string uri = "ftp://" + ftpServerIP + "/" + fileInf.Name;
            FtpWebRequest reqFTP;

            // Create FtpWebRequest object from the Uri provided
            reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + fileInf.Name));

            // Provide the WebPermission Credintials
            reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);

            // By default KeepAlive is true, where the control connection is not closed
            // after a command is executed.
            reqFTP.KeepAlive = false;

            // Specify the command to be executed.
            reqFTP.Method = WebRequestMethods.Ftp.UploadFile;

            // Specify the data transfer type.
            reqFTP.UseBinary = true;

            // Notify the server about the size of the uploaded file
            reqFTP.ContentLength = fileInf.Length;

            // The buffer size is set to 2kb
            int buffLength = 2048;
            byte[] buff = new byte[buffLength];
            int contentLen;

            // Opens a file stream (System.IO.FileStream) to read the file to be uploaded
            FileStream fs = fileInf.OpenRead();

            try
            {
                // Stream to which the file to be upload is written
                Stream strm = reqFTP.GetRequestStream();

                // Read from the file stream 2kb at a time
                contentLen = fs.Read(buff, 0, buffLength);

                // Till Stream content ends
                while (contentLen != 0)
                {
                    // Write Content from the file stream to the FTP Upload Stream
                    strm.Write(buff, 0, contentLen);
                    contentLen = fs.Read(buff, 0, buffLength);
                }

                // Close the file stream and the Request Stream
                strm.Close();
                fs.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Upload Error");
            }
        }
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="fileName"></param>
        public void DeleteFTP(string fileName)
        {
            try
            {
                string uri = "ftp://" + ftpServerIP + "/" + fileName;
                FtpWebRequest reqFTP;
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + fileName));

                reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                reqFTP.KeepAlive = false;
                reqFTP.Method = WebRequestMethods.Ftp.DeleteFile;

                string result = String.Empty;
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                long size = response.ContentLength;
                Stream datastream = response.GetResponseStream();
                StreamReader sr = new StreamReader(datastream);
                result = sr.ReadToEnd();
                sr.Close();
                datastream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "FTP 2.0 Delete");
            }
        }
        /// <summary>
        /// 要得到文件名,文件夾,文件地址,文件大小,文件建立時間
        /// 获取文件和文件夹列表
        /// </summary>
        /// <returns></returns>
        private string[] GetFilesDetailList()
        {
            string[] downloadFiles;
            try
            {
                StringBuilder result = new StringBuilder();
                FtpWebRequest ftp;
                ftp = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/"));
                ftp.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
                WebResponse response = ftp.GetResponse();
                StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default); //遍曆讀文件信息
                string line = reader.ReadLine();

                while (line != null)
                {
                    result.Append(line);
                    result.Append("\n");
                    line = reader.ReadLine();
                }

                result.Remove(result.ToString().LastIndexOf("\n"), 1);
                reader.Close();
                response.Close();
                return result.ToString().Split('\n');
                //MessageBox.Show(result.ToString().Split('\n'));
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
                downloadFiles = null;
                return downloadFiles;
            }
        }
        /// <summary>
        /// 获取文件列表
        /// </summary>
        /// <returns></returns>
        public string[] GetFileList()
        {
            string[] downloadFiles;
            StringBuilder result = new StringBuilder();
            FtpWebRequest reqFTP;
            try
            {
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/"));
                reqFTP.UseBinary = true;
                reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;
                WebResponse response = reqFTP.GetResponse();
                StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);

                //MessageBox.Show(reader.ReadToEnd());
                string line = reader.ReadLine();
                while (line != null)
                {
                    result.Append(line);
                    result.Append("\n");
                    line = reader.ReadLine();
                }
                result.Remove(result.ToString().LastIndexOf('\n'), 1);
                reader.Close();
                response.Close();
                //MessageBox.Show(response.StatusDescription);
                return result.ToString().Split('\n');
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
                downloadFiles = null;
                return downloadFiles;
            }
        }
        /// <summary>
        /// 下载
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileName"></param>
        private void Download(string filePath, string fileName)
        {
            FtpWebRequest reqFTP;
            try
            {
                //filePath = <<The full path where the file is to be created.>>, 
                //fileName = <<Name of the file to be created(Need not be the name of the file on FTP server).>>
                FileStream outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create);

                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + fileName));
                reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
                reqFTP.UseBinary = true;
                reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                Stream ftpStream = response.GetResponseStream();
                long cl = response.ContentLength;
                int bufferSize = 2048;
                int readCount;
                byte[] buffer = new byte[bufferSize];

                readCount = ftpStream.Read(buffer, 0, bufferSize);
                while (readCount > 0)
                {
                    outputStream.Write(buffer, 0, readCount);
                    readCount = ftpStream.Read(buffer, 0, bufferSize);
                }

                ftpStream.Close();
                outputStream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        /// <summary>
        /// 上传
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnUpload_Click(object sender, EventArgs e)
        {
            OpenFileDialog opFilDlg = new OpenFileDialog();
            if (opFilDlg.ShowDialog() == DialogResult.OK)
            {
                Upload(opFilDlg.FileName);
            }
        }
        /// <summary>
        /// 下载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDownload_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fldDlg = new FolderBrowserDialog();
            if (txtUpload.Text.Trim().Length > 0)
            {
                if (fldDlg.ShowDialog() == DialogResult.OK)
                {
                    Download(fldDlg.SelectedPath, txtUpload.Text.Trim());
                }
            }
            else
            {
                MessageBox.Show("Please enter the File name to download");
            }
        }
        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btndelete_Click(object sender, EventArgs e)
        {
            OpenFileDialog fldDlg = new OpenFileDialog();
            if (txtUpload.Text.Trim().Length > 0)
            {
                DeleteFTP(txtUpload.Text.Trim());
            }
            else
            {
                MessageBox.Show("Please enter the File name to delete");
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        private long GetFileSize(string filename)
        {
            FtpWebRequest reqFTP;
            long fileSize = 0;
            try
            {
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + filename));
                reqFTP.Method = WebRequestMethods.Ftp.GetFileSize;
                reqFTP.UseBinary = true;
                reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                Stream ftpStream = response.GetResponseStream();
                fileSize = response.ContentLength;

                ftpStream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            return fileSize;
        }
        /// <summary>
        /// 计算文件大小
        /// </summary>
        /// <returns></returns>
        public string setSize(long size)
        {
            string strszie = string.Empty;

            long g = 1024 * 1024 * 1024;
            long m = 1024 * 1024;
            long k = 1024;
            if (size < k && size >= 1)
            {
                strszie = size.ToString("0.00") + "B";
            }
            else if (size < m && size >= 1024)
            {
                strszie = (size / k).ToString("0.00") + "KB";
            }
            else if (size < g && size >= m)
            {
                strszie = (size / m).ToString("0.00") + "MB";
            }
            else if (size >= g)
            {
                strszie = (size / g).ToString("0.00") + "GB";
            }

            return strszie;

        }
        /// <summary>
        /// 改名
        /// </summary>
        /// <param name="currentFilename"></param>
        /// <param name="newFilename"></param>
        private void Rename(string currentFilename, string newFilename)
        {
            FtpWebRequest reqFTP;
            try
            {
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + currentFilename));
                reqFTP.Method = WebRequestMethods.Ftp.Rename;
                reqFTP.RenameTo = newFilename;
                reqFTP.UseBinary = true;
                reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                Stream ftpStream = response.GetResponseStream();

                ftpStream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dirName"></param>
        private void MakeDir(string dirName)
        {
            FtpWebRequest reqFTP;
            try
            {
                // dirName = name of the directory to create.
                reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + dirName));
                reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory;
                reqFTP.UseBinary = true;
                reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                Stream ftpStream = response.GetResponseStream();

                ftpStream.Close();
                response.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        /// <summary>
        /// 文件大小
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnFileSize_Click(object sender, EventArgs e)
        {
            long size = GetFileSize(txtUpload.Text.Trim());
            string s = setSize(size);
            //MessageBox.Show(size.ToString() + " bytes");
            MessageBox.Show(s);
        }
        /// <summary>
        /// 改名
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            Rename(txtCurrentFilename.Text.Trim(), txtNewFilename.Text.Trim());
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnewDir_Click(object sender, EventArgs e)
        {
            MakeDir(txtNewDir.Text.Trim());
        }
        /// <summary>
        /// 显示文件列表
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnLstFiles_Click(object sender, EventArgs e)
        {
            string[] filenames = GetFileList();
            lstFiles.Items.Clear();
            foreach (string filename in filenames)
            {
                lstFiles.Items.Add(filename);
            }
        }
        /// <summary>
        /// 显示文件和文件夹列表
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnFileDetailList_Click(object sender, EventArgs e)
        {
            string[] filenames = GetFilesDetailList();
            lstFiles.Items.Clear();
            foreach (string filename in filenames)
            {
                lstFiles.Items.Add(filename);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnFTPSave_Click(object sender, EventArgs e)
        {
            ftpServerIP = txtServerIP.Text.Trim();
            ftpUserID = txtUsername.Text.Trim();
            ftpPassword = txtPassword.Text.Trim();
            btnFTPSave.Enabled = false;
        }

        private void txtServerIP_TextChanged(object sender, EventArgs e)
        {
            btnFTPSave.Enabled = true;
        }

        private void txtUsername_TextChanged(object sender, EventArgs e)
        {
            btnFTPSave.Enabled = true;
        }

        private void txtPassword_TextChanged(object sender, EventArgs e)
        {
            btnFTPSave.Enabled = true;
        }
    }
}

  

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

namespace ftpdemo
{
    /// <summary>
    /// 
    /// </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 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;

            // 切换到初始目录
            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)
        {
            bool isok = false;
            try
            {
                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));
                    }
                }
                isok = true;
            }
            catch (Exception ex)
            {

                ex.Message.ToString();

            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="strFileName"></param>
        public bool Putload(string strFileName)
        {
            bool isok = false;
            try
            {
                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));
                    }
                }
                isok = true;
            }
            catch (Exception ex)
            {

                ex.Message.ToString();

            }
            return isok;
        }
        #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
    }
}

  测试:

     /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            FTPClient client = new FTPClient(ftpServer, "/", user, pwd, int.Parse(port));
            client.Connect();
            GetFolder("*", remotingFolder, client, CreateFolder());
            client.DisConnect();
            ClearFolder();
            MessageBox.Show("下载完毕");
            System.Threading.Thread.Sleep(3000);
        }

        /// <summary>
        /// 在本地目录下创建一个以日期为名称的目录,我做这个ftp的主要目的是为了每天都备份
        /// </summary>
        /// <returns>创建的目录名</returns>
        private  string CreateFolder()
        {
            string folder = localFolder + "\\" + DateTime.Now.ToShortDateString();
            if (!Directory.Exists(folder))
                Directory.CreateDirectory(folder);

            return folder;
        }

        /// <summary>
        /// 在下载结束后清空程序目录的多余文件
        /// </summary>
        private  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  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);  //下载文件
                        MessageBox.Show("文件" + folder + info + "已经下载");
                    }
                }
            }

        }
        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {          
            try
            {





                OpenFileDialog op = new OpenFileDialog();
                op.InitialDirectory = Application.StartupPath;
                op.RestoreDirectory = true;
                op.Filter = "压缩文件(*.zip)|*.zip|压缩文件(*.rar)|*.rar|所有文件(*.*)|*.*";
                if (op.ShowDialog() == DialogResult.OK)
                {
                    string aa = op.FileName;

                    //上传在根目录下
                    //FTPClient client = new FTPClient(ftpServer, "/", user, pwd, int.Parse(port));
                    //client.Connect();
                    //client.Put(@"C:\nltk_data\tokenizers\punkt.zip");
                    //System.Threading.Thread.Sleep(3000);


                    //上传在根目录下
                    FTPClient client = new FTPClient(ftpServer, "/", user, pwd, int.Parse(port));
                    client.Connect();
                    bool isok = client.Putload(aa);
                    System.Threading.Thread.Sleep(3000);

                    //FileUpDownload.FtpServerIP = ftpServer;
                    //FileUpDownload.FtpUserID = user;
                    //FileUpDownload.FtpPassword = pwd;
                    //全路径  
                   // bool isok = FileUpDownload.FtpUploadFile(aa);  //上传成功 //在根目录下

                    //
                    //bool isok = Upload(aa); //在根目录下


                    if (isok)
                    {
                        MessageBox.Show("OK!");
                    }
                }




            }
            catch (Exception ex)
            {
                MessageBox.Show("erro");
            }


        }


        /// <summary>
        /// Method to upload the specified file to the specified FTP Server
        /// </summary>
        /// <param name="filename">file full name to be uploaded</param>
        private bool Upload(string filename)
        {
            bool isok = false;
            FileInfo fileInf = new FileInfo(filename);
            string uri = "ftp://" + ftpServer + "/" + fileInf.Name; //+ localFolder +
            FtpWebRequest reqFTP;

            // Create FtpWebRequest object from the Uri provided
            reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServer + "/" + fileInf.Name));//+ localFolder + "/"

            // Provide the WebPermission Credintials
            reqFTP.Credentials = new NetworkCredential(user, pwd);

            // By default KeepAlive is true, where the control connection is not closed
            // after a command is executed.
            reqFTP.KeepAlive = false;

            // Specify the command to be executed.
            reqFTP.Method = WebRequestMethods.Ftp.UploadFile;

            // Specify the data transfer type.
            reqFTP.UseBinary = true;

            // Notify the server about the size of the uploaded file
            reqFTP.ContentLength = fileInf.Length;

            // The buffer size is set to 2kb
            int buffLength = 2048;
            byte[] buff = new byte[buffLength];
            int contentLen;

            // Opens a file stream (System.IO.FileStream) to read the file to be uploaded
            FileStream fs = fileInf.OpenRead();

            try
            {
                // Stream to which the file to be upload is written
                Stream strm = reqFTP.GetRequestStream();

                // Read from the file stream 2kb at a time
                contentLen = fs.Read(buff, 0, buffLength);

                // Till Stream content ends
                while (contentLen != 0)
                {
                    // Write Content from the file stream to the FTP Upload Stream
                    strm.Write(buff, 0, contentLen);
                    contentLen = fs.Read(buff, 0, buffLength);
                }

                // Close the file stream and the Request Stream
                isok = true;
                strm.Close();
                fs.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Upload Error");
            }
            return isok;
        }

  

  /// <summary>
    /// ftp帮助类
    /// </summary>
    public class FtpHelper
    {
        private string ftpHostIP { get; set; }
        private string username { get; set; }
        private string password { get; set; }
        private string ftpURI { get { return string.Format("ftp://{0}/", ftpHostIP); } }

        /// <summary>
        /// 初始化ftp参数
        /// </summary>
        /// <param name="ftpHostIP">ftp主机IP</param>
        /// <param name="username">ftp账户</param>
        /// <param name="password">ftp密码</param>
        public FtpHelper(string ftpHostIP, string username, string password)
        {
            this.ftpHostIP = ftpHostIP;
            this.username = username;
            this.password = password;
        }

        /// <summary>
        /// 异常方法委托,通过Lamda委托统一处理异常,方便改写
        /// </summary>
        /// <param name="method">当前执行的方法</param>
        /// <param name="action"></param>
        /// <returns></returns>
        private bool MethodInvoke(string method, Action action)
        {
            if (action != null)
            {
                try
                {
                    action();
                    //Logger.Write2File($@"FtpHelper.{method}:执行成功");
                    //FluentConsole.Magenta.Line($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行成功");
                    return true;
                }
                catch (Exception ex)
                {
                    //FluentConsole.Red.Line($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行失败:\n {ex}");
                    // Logger.Write2File(FtpHelper({ftpHostIP},{username},{password}).{method}:执行失败 \r\n{ex}");
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 异常方法委托,通过Lamda委托统一处理异常,方便改写
        /// </summary>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="method"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        private T MethodInvoke<T>(string method, Func<T> func)
        {
            if (func != null)
            {
                try
                {
                    //FluentConsole.Magenta.Line($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行成功");
                    //Logger.Write2File($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行成功");
                    return func();
                }
                catch (Exception ex)
                {
                    //FluentConsole.Red.Line($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行失败:").Line(ex);
                    // Logger.Write2File($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行失败 \r\n{ex}");
                    return default(T);
                }
            }
            else
            {
                return default(T);
            }
        }
        /// <summary>
        /// https://stackoverflow.com/questions/17451620/reusing-ftpwebrequest
        /// </summary>
        /// <param name="URI"></param>
        /// <returns></returns>
        private FtpWebRequest GetRequest(string URI)
        {
            //根据服务器信息FtpWebRequest创建类的对象
            FtpWebRequest result = (FtpWebRequest)WebRequest.Create(URI);
            
            //result.Credentials = new NetworkCredential(username, password);

            result.Method = WebRequestMethods.Ftp.GetFileSize;
            NetworkCredential nc = new NetworkCredential(username, password);
            result.Credentials = nc;

            //result.UseBinary = true;
            //result.UsePassive = true;
            //result.KeepAlive = true;

            result.KeepAlive = false;
            result.UsePassive = false;
            result.UseBinary = true;

            return result;
        }

        /// <summary> 上传文件</summary>
        /// <param name="filePath">需要上传的文件路径</param>
        /// <param name="dirName">目标路径</param>
        public bool UploadFile(string filePath, string dirName = "")
        {
            FileInfo fileInfo = new FileInfo(filePath);
            if (dirName != "")
            {
                //if(DirectoryExist(dirName)
                MakeDir(dirName);//检查文件目录,不存在就自动创建
            }


            string uri =ftpURI+dirName;// Path.Combine(ftpURI, dirName, fileInfo.Name);
            return MethodInvoke(@"uploadFile({filePath},{dirName})", () =>
            {
                FtpWebRequest ftp = GetRequest(uri);
                ftp.Method = WebRequestMethods.Ftp.UploadFile;
                ftp.ContentLength = fileInfo.Length;
                int buffLength = 2048;
                byte[] buff = new byte[buffLength];
                int contentLen;
                using (FileStream fs = fileInfo.OpenRead())
                {
                    using (Stream strm = ftp.GetRequestStream())
                    {
                        contentLen = fs.Read(buff, 0, buffLength);
                        while (contentLen != 0)
                        {
                            strm.Write(buff, 0, contentLen);
                            contentLen = fs.Read(buff, 0, buffLength);
                        }
                        strm.Close();
                    }
                    fs.Close();
                }
            });
        }

        /// <summary>
        /// 从一个目录将其内容复制到另一目录
        /// </summary>
        /// <param name="localDir">源目录</param>
        /// <param name="DirName">目标目录</param>
        public void UploadAllFile(string localDir, string DirName = "")
        {
            string localDirName = string.Empty;
            int targIndex = localDir.LastIndexOf("\\");
            if (targIndex > -1 && targIndex != (localDir.IndexOf(":\\") + 1))
                localDirName = localDir.Substring(0, targIndex);
            localDirName = localDir.Substring(targIndex + 1);
            string newDir = Path.Combine(DirName, localDirName);
            MethodInvoke(@"UploadAllFile({localDir},{DirName})", () =>
            {
                MakeDir(newDir);
                DirectoryInfo directoryInfo = new DirectoryInfo(localDir);
                FileInfo[] files = directoryInfo.GetFiles();
                //复制所有文件  
                foreach (FileInfo file in files)
                {
                    UploadFile(file.FullName, newDir);
                }
                //最后复制目录  
                DirectoryInfo[] directoryInfoArray = directoryInfo.GetDirectories();
                foreach (DirectoryInfo dir in directoryInfoArray)
                {
                    UploadAllFile(Path.Combine(localDir, dir.Name), newDir);
                }
            });
        }

        /// <summary> 
        /// 删除单个文件
        /// </summary>
        /// <param name="filePath"></param>
        public bool DelFile(string filePath)
        {
            string uri = Path.Combine(ftpURI, filePath);
            return MethodInvoke(@"DelFile({filePath})", () =>
            {
                FtpWebRequest ftp = GetRequest(uri);
                ftp.Method = WebRequestMethods.Ftp.DeleteFile;
                FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
                response.Close();
            });
        }

        /// <summary> 
        /// 删除最末及空目录
        /// </summary>
        /// <param name="dirName"></param>
        private bool DelDir(string dirName)
        {
            string uri = Path.Combine(ftpURI, dirName);
            return MethodInvoke(@"DelDir({dirName})", () =>
            {
                FtpWebRequest ftp = GetRequest(uri);
                ftp.Method = WebRequestMethods.Ftp.RemoveDirectory;
                FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
                response.Close();
            });
        }

        /// <summary> 删除目录或者其目录下所有的文件 </summary>
        /// <param name="dirName">目录名称</param>
        /// <param name="ifDelSub">是否删除目录下所有的文件</param>
        public bool DelAll(string dirName)
        {
            var list = GetAllFtpFile(new List<ActFile>(),dirName);
            if (list == null)   return  DelDir(dirName);
            if (list.Count==0)  return  DelDir(dirName);//删除当前目录
            var newlist = list.OrderByDescending(x => x.level);
            foreach (var item in newlist)
            {
                //FluentConsole.Yellow.Line(@"level:{item.level},isDir:{item.isDir},path:{item.path}");
            }
            string uri = Path.Combine(ftpURI, dirName);
            return MethodInvoke(@"DelAll({dirName})", () =>
            {
                foreach (var item in newlist)
                {
                    if (item.isDir)//判断是目录调用目录的删除方法
                        DelDir(item.path);
                    else
                        DelFile(item.path);
                }
                DelDir(dirName);//删除当前目录
                return true;
            });
        }

        /// <summary>
        /// 下载单个文件
        /// </summary>
        /// <param name="ftpFilePath">从ftp要下载的文件路径</param>
        /// <param name="localDir">下载至本地路径</param>
        /// <param name="filename">文件名</param>
        public bool DownloadFile(string ftpFilePath, string saveDir)
        {
            string filename = ftpFilePath.Substring(ftpFilePath.LastIndexOf("\\") + 1);
            string tmpname = Guid.NewGuid().ToString();
            string uri = ftpURI+ftpFilePath;//Path.Combine(ftpURI, ftpFilePath);//
            return MethodInvoke(@"DownloadFile({ftpFilePath},{saveDir},{filename})", () =>
            {
                if (!Directory.Exists(saveDir)) Directory.CreateDirectory(saveDir);
                FtpWebRequest ftp = GetRequest(uri);
                ftp.Method = WebRequestMethods.Ftp.DownloadFile;
                using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())
                {
                    using (Stream responseStream = response.GetResponseStream())
                    {
                        using (FileStream fs = new FileStream(Path.Combine(saveDir, filename), FileMode.CreateNew)) //Path.Combine(saveDir, filename)
                        {
                            byte[] buffer = new byte[2048];
                            int read = 0;
                            do
                            {
                                read = responseStream.Read(buffer, 0, buffer.Length);
                                fs.Write(buffer, 0, read);
                            } while (!(read == 0));
                            responseStream.Close();
                            fs.Flush();
                            fs.Close();
                        }
                        responseStream.Close();
                    }
                    response.Close();
                }
            });
        }

        /// <summary>    
        /// 从FTP下载整个文件夹    
        /// </summary>    
        /// <param name="dirName">FTP文件夹路径</param>    
        /// <param name="saveDir">保存的本地文件夹路径</param>    
        public void DownloadAllFile(string dirName, string saveDir)
        {
            MethodInvoke(@"DownloadAllFile({dirName},{saveDir})", () =>
            {
                List<ActFile> files = GetFtpFile(dirName);
                if (!Directory.Exists(saveDir))
                {
                    Directory.CreateDirectory(saveDir);
                }
                foreach (var f in files)
                {
                    if (f.isDir) //文件夹,递归查询  
                    {
                        DownloadAllFile(Path.Combine(dirName,f.name), Path.Combine(saveDir ,f.name));
                    }
                    else //文件,直接下载  
                    {
                        DownloadFile(Path.Combine(dirName,f.name), saveDir);
                    }
                }
            });
        }

        /// <summary>
        /// 获取当前目录下的目录及文件
        /// </summary>
        /// param name="ftpfileList"></param>
        /// <param name="dirName"></param>
        /// <returns></returns>
        public List<ActFile> GetFtpFile(string dirName,int ilevel = 0)
        {
            var ftpfileList = new List<ActFile>();
            string uri = Path.Combine(ftpURI, dirName);
            return MethodInvoke(@"GetFtpFile({dirName})", () =>
            {
                var a = new List<List<string>>();
                FtpWebRequest ftp = GetRequest(uri);
                ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
                Stream stream = ftp.GetResponse().GetResponseStream();
                using (StreamReader sr = new StreamReader(stream))
                {
                    string line = sr.ReadLine();
                    while (!string.IsNullOrEmpty(line))
                    {
                        ftpfileList.Add(new ActFile { isDir = line.IndexOf("<DIR>") > -1, name = line.Substring(39).Trim(), path = Path.Combine(dirName, line.Substring(39).Trim()), level= ilevel });
                        line = sr.ReadLine();
                    }
                    sr.Close();
                }
                return ftpfileList;
            });


        }

        /// <summary>
        /// 获取FTP目录下的所有目录及文件包括其子目录和子文件
        /// </summary>
        /// param name="result"></param>
        /// <param name="dirName"></param>
        /// <returns></returns>
        public List<ActFile> GetAllFtpFile(List<ActFile> result,string dirName, int level = 0)
        {
            var ftpfileList = new List<ActFile>();
            string uri = Path.Combine(ftpURI, dirName);
            return MethodInvoke(@"GetAllFtpFile({dirName})", () =>
            {
                 ftpfileList = GetFtpFile(dirName, level);
                result.AddRange(ftpfileList);
                var newlist = ftpfileList.Where(x => x.isDir).ToList();
                foreach (var item in newlist)
                {
                    GetAllFtpFile(result,item.path, level+1);
                }
                return result;
            });

        }

        /// <summary>
        /// 检查目录是否存在
        /// </summary>
        /// <param name="dirName"></param>
        /// <param name="currentDir"></param>
        /// <returns></returns>
        public bool CheckDir(string dirName, string currentDir) // = ""
        {
            string uri = ftpURI+currentDir; //Path.Combine(ftpURI, currentDir);
            if (!string.IsNullOrEmpty(currentDir))
            {
                return MethodInvoke(@"CheckDir({dirName}{currentDir})", () =>
                {
                    FtpWebRequest ftp = GetRequest(uri);
                    ftp.UseBinary = true;
                    ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails; //获取FTP目录下所有的文件和文件夹的名字
                    // WebRequestMethods.Ftp.ListDirectory;
                    Stream stream = ftp.GetResponse().GetResponseStream();
                    using (StreamReader sr = new StreamReader(stream))
                    {
                        string line = sr.ReadLine();
                        while (!string.IsNullOrEmpty(line))
                        {
                            if (line.IndexOf("<DIR>") > -1)
                            {
                                if (line.Substring(39).Trim() == dirName)
                                    return true;
                            }
                            line = sr.ReadLine();
                        }
                        sr.Close();
                    }
                    stream.Close();
                    return false;
                });
            }
            else
            {
                return false;
            }

        }

        ///  </summary>
        /// 在ftp服务器上创建指定目录,父目录不存在则创建
        /// </summary>
        /// <param name="dirName">创建的目录名称</param>
        public bool MakeDir(string dirName)
        {
            var dirs = dirName.Split('\\').ToList();//针对多级目录分割
            string currentDir = string.Empty;
            return MethodInvoke(@"MakeDir({dirName})", () =>
            {
                foreach (var dir in dirs)
                {
                    //涂聚文 Geovin Du
                    //if (string.IsNullOrEmpty(dir))
                    //{
                    //    continue;
                    //}
                    if (!string.IsNullOrEmpty(dir))
                    {
                        //存在问题,判断是文件夹,再判断是否存在此文件夹,不存在也创建
                        if (!dir.Contains(".")) //如果是文件不考虑
                        {
                            currentDir = currentDir + "/" + dir;//Path.Combine(currentDir, dir);
                            string uri = ftpURI + currentDir;// Path.Combine(ftpURI, currentDir);
                            if (!DirectoryExist(uri))//检查目录不存在则创建CheckDir(dir, currentDir)  //要考虑不是文件,是文件夹。
                            {
                                FtpWebRequest ftp = GetRequest(uri);
                                ftp.Method = WebRequestMethods.Ftp.MakeDirectory;  //无权限
                                FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
                                response.Close();
                            }
                        }
                    }
                }

            });

        }
        /// <summary>
        /// 文件夹是否存在
        /// </summary>
        /// <param name="URI"></param>
        /// <returns></returns>
        public bool DirectoryExist(string uri)
        {

            FtpWebRequest reqFTP = GetRequest(uri);
           // FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
            //reqFTP.Credentials = new NetworkCredential("", "");
            reqFTP.Method = WebRequestMethods.Ftp.ListDirectory; //PrintWorkingDirectory ListDirectoryDetails
            reqFTP.UseBinary = true;
            try
            {
                FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
                StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                string line = reader.ReadLine();
                reader.Close();
                response.Close();
                if (line != null)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                string e = ex.Message;
                return false;
            }
        }
  
        /// <summary>
        /// Normalizes the URI.
        /// </summary>
        /// <param name="uri">The URI.</param>
        /// <returns>A normalized URI</returns>
        private Uri NormalizeUri(Uri uri)
        {
            if (uri == null)
                throw new ArgumentNullException("uri");

            if (uri.Scheme != Uri.UriSchemeFtp)
                throw new ArgumentException("The URI isn't a valid FTP URI", "uri");

            string path = uri.AbsoluteUri;

            //Cut the "ftp://" off
            path = path.Substring(6);

            path = path.Replace("//", "/").Replace(@"\\", "/").Replace(@"\", "/");

            return new Uri("ftp://" + path);
        }
        /// <summary>文件重命名 </summary>
        /// <param name="currentFilename">当前名称</param>
        /// <param name="newFilename">重命名名称</param>
        /// <param name="currentFilename">所在的目录</param>
        public bool Rename(string currentFilename, string newFilename, string dirName = "")
        {
            string uri = Path.Combine(ftpURI, dirName, currentFilename);
            return MethodInvoke(@"Rename({currentFilename},{newFilename},{dirName})", () =>
            {
                FtpWebRequest ftp = GetRequest(uri);
                ftp.Method = WebRequestMethods.Ftp.Rename;
                ftp.RenameTo = newFilename;
                FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
                response.Close();
            });
        }
    }
    /// <summary>
    /// 
    /// </summary>
    public class ActFile
    {
        public int level { get; set; }
        public bool isDir { get; set; }
        public string name { get; set; }
        public string path { get; set; }
    }

  测试:

     /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            var ftp = new FtpHelper(ftpServer, user, pwd);//初始化ftp,创建ftp对象

            //ftp.DelAll("test");//删除ftptest目录及其目录下的所有文件
           // ftp.UploadAllFile("F:\\涂聚文维修方案000.pdf");//上传单个文件到指定目录
            //ftp.UploadAllFile("F:\\test");//将本地test目录的所有文件上传
          // bool ok= ftp.DownloadFile(@"\htdocs\涂聚文维修方案.pdf", "F:\\");//下载单个目录
           // ftp.DownloadAllFile("test", "F:\\test1");//批量下载整个目录
            //ftp.MakeDir("aaa\\bbb\\ccc\\ddd");//创建多级目录

            bool ok = ftp.UploadFile("F:\\涂聚文维修方案000.pdf", @"\htdocs\geovindu\涂聚文维修方案000.pdf");  //上传成功
           if (ok)
           {
               MessageBox.Show("ok");
           }
           else
           {
               MessageBox.Show("no");
           }
        }

  https://github.com/hgupta9/FluentFTP

https://fluentftp.codeplex.com/

测试示例:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Configuration;
using FluentFTP;
using System.Threading;
using System.Net;


namespace FluentFtpDemo
{

    /// <summary>
    /// 涂聚文测试示例
    /// Geovin Du
    /// </summary>
    public partial class Form1 : Form
    {
        string remotingFolder = System.Configuration.ConfigurationManager.AppSettings["remotingFolder"];  //远程ftp文件目录
        string localFolder = System.Configuration.ConfigurationManager.AppSettings["localFolder"];  //要下载到的本地目录
        string ftpServer = System.Configuration.ConfigurationManager.AppSettings["ftpServer"];  //ftp服务器
        string user = System.Configuration.ConfigurationManager.AppSettings["user"];  //用户名
        string pwd = System.Configuration.ConfigurationManager.AppSettings["pwd"];  //密码
        string port = System.Configuration.ConfigurationManager.AppSettings["port"];  //端口
        string remotingFolderOther = System.Configuration.ConfigurationManager.AppSettings["remotingFolderOther"];

        static ManualResetEvent m_reset = new ManualResetEvent(false);
        /// <summary>
        /// 
        /// </summary>
        public Form1()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {

        }
        /// <summary>
        /// 判断文件夹是否存在
        /// </summary>
        public  void BeginDirectoryExists()
        {
            // The using statement here is OK _only_ because m_reset.WaitOne()
            // causes the code to block until the async process finishes, otherwise
            // the connection object would be disposed early. In practice, you
            // typically would not wrap the following code with a using statement.
            using (FtpClient conn = new FtpClient())
            {
                m_reset.Reset();

                conn.Host = ftpServer;
                conn.Credentials = new NetworkCredential(user, pwd);
                conn.BeginDirectoryExists("/htdocs/admin", new AsyncCallback(DirectoryExistsCallback), conn);

                m_reset.WaitOne();
                conn.Disconnect();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ar"></param>
        void DirectoryExistsCallback(IAsyncResult ar)
        {
            FtpClient conn = ar.AsyncState as FtpClient;

            try
            {
                if (conn == null)
                    throw new InvalidOperationException("The FtpControlConnection object is null!");

                MessageBox.Show("Directory Exiss: " + conn.EndDirectoryExists(ar));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                m_reset.Set();
            }
        }
        /// <summary>
        /// 文件是否存在
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
           
           
            BeginFileExists();
        }
        /// <summary>
        /// 判断文件是否存在
        /// </summary>
        public  void BeginFileExists()
        {
            // The using statement here is OK _only_ because m_reset.WaitOne()
            // causes the code to block until the async process finishes, otherwise
            // the connection object would be disposed early. In practice, you
            // typically would not wrap the following code with a using statement.
            using (FtpClient conn = new FtpClient())
            {
                m_reset.Reset();
                conn.Encoding = Encoding.UTF8; //设置编码
                conn.Host = ftpServer;
                conn.Credentials = new NetworkCredential(user, pwd);
                conn.Connect();
                string file = (@"\htdocs\法律法规依据目录.pdf");
                //中文文件名出问题
                conn.BeginFileExists(file, new AsyncCallback(BeginFileExistsCallback), conn);//涂聚文维修方案.pdf

                m_reset.WaitOne();
                conn.Disconnect();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ar"></param>
        void BeginFileExistsCallback(IAsyncResult ar)
        {
            FtpClient conn = ar.AsyncState as FtpClient;

            try
            {
                if (conn == null)
                    throw new InvalidOperationException("The FtpControlConnection object is null!");

                MessageBox.Show("File exists: " + conn.EndFileExists(ar));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                m_reset.Set();
            }
        }

        /// <summary>
        /// GB2312转换成UTF8
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static string gb2312_utf8(string text)
        {
            //声明字符集   
            System.Text.Encoding utf8, gb2312;
            //gb2312   
            gb2312 = System.Text.Encoding.GetEncoding("gb2312");
            //utf8   
            utf8 = System.Text.Encoding.GetEncoding("utf-8");
            byte[] gb;
            gb = gb2312.GetBytes(text);
            gb = System.Text.Encoding.Convert(gb2312, utf8, gb);
            //返回转换后的字符   
            return utf8.GetString(gb);
        }

        /// <summary>
        /// UTF8转换成GB2312
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static string utf8_gb2312(string text)
        {
            //声明字符集   
            System.Text.Encoding utf8, gb2312;
            //utf8   
            utf8 = System.Text.Encoding.GetEncoding("utf-8");
            //gb2312   
            gb2312 = System.Text.Encoding.GetEncoding("gb2312");
            byte[] utf;
            utf = utf8.GetBytes(text);
            utf = System.Text.Encoding.Convert(utf8, gb2312, utf);
            //返回转换后的字符   
            return gb2312.GetString(utf);
        }
         /// <summary>
         /// 文件夹是否存在
         /// </summary>
         /// <param name="sender"></param>
         /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            BeginDirectoryExists();
        }
        /// <summary>
        /// 创建文件夹
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            BeginCreateDirectory();
        }
        /// <summary>
        /// 创建文件夹
        /// </summary>
        public void BeginCreateDirectory()
        {
            // The using statement here is OK _only_ because m_reset.WaitOne()
            // causes the code to block until the async process finishes, otherwise
            // the connection object would be disposed early. In practice, you
            // typically would not wrap the following code with a using statement.
            using (FtpClient conn = new FtpClient())
            {
                m_reset.Reset();

                conn.Host = ftpServer;
                conn.Encoding = Encoding.UTF8;
                conn.Credentials = new NetworkCredential(user, pwd);
               // conn.DeleteDirectory("/test");
                conn.BeginCreateDirectory("/htdocs/geovindu/created", true,new AsyncCallback(CreateDirectoryCallback), conn);
                m_reset.WaitOne();
                conn.Disconnect();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ar"></param>
        void CreateDirectoryCallback(IAsyncResult ar)
        {
            FtpClient conn = ar.AsyncState as FtpClient;

            try
            {
                if (conn == null)
                    throw new InvalidOperationException("The FtpControlConnection object is null!");

                conn.EndCreateDirectory(ar);
                MessageBox.Show("创建成功!");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                m_reset.Set();
            }
        }
        /// <summary>
        /// 删除文件夹
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            BeginDeleteDirectory();
        }
        /// <summary>
        /// 
        /// </summary>
        public  void BeginDeleteDirectory()
        {
            // The using statement here is OK _only_ because m_reset.WaitOne()
            // causes the code to block until the async process finishes, otherwise
            // the connection object would be disposed early. In practice, you
            // typically would not wrap the following code with a using statement.
            using (FtpClient conn = new FtpClient())
            {
                m_reset.Reset();
                conn.Host = ftpServer;
                conn.Encoding = Encoding.UTF8;
                conn.Credentials = new NetworkCredential(user, pwd);
                //conn.CreateDirectory("/some/test/directory");
                conn.BeginDeleteDirectory("/htdocs/geovindu", new AsyncCallback(DeleteDirectoryCallback), conn);
                m_reset.WaitOne();
                conn.Disconnect();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ar"></param>
        void DeleteDirectoryCallback(IAsyncResult ar)
        {
            FtpClient conn = ar.AsyncState as FtpClient;

            try
            {
                if (conn == null)
                    throw new InvalidOperationException("The FtpControlConnection object is null!");

                conn.EndDeleteDirectory(ar);
                MessageBox.Show("删除成功");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                m_reset.Set();
            }
        }
    }
}

  

posted @ 2017-07-26 14:14  ®Geovin Du Dream Park™  阅读(694)  评论(0编辑  收藏  举报