C# FTP工具类

许多博客提供的ftp工具类中,方法被调时需要先移动ftp服务器当前所在目录,并且存在bug,非常不爽。本人加以改动,符合调用习惯,并经过实际项目测试。

FTP工具类代码

    /// <summary>
    /// Ftp工具类
    /// </summary>
    public class FtpHelper
    {
        private string ftpHostIP;
        private string username;
        private string password;
        /// <summary>
        /// 服务器用了啥ftp软件
        /// </summary>
        public FtpServerApp FtpApp { get; set; } = FtpServerApp.Unknown;
        /// <summary>
        /// 服务器根目录
        /// </summary>
        private string ftpURI
        {
            get { return "ftp://" + 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>
        /// 测试连接
        /// </summary>
        public bool checkConnect()
        {
            try
            {
                //TcpClient m_connection = new TcpClient();
                //m_connection.Connect(ftpHostIP, 21);
                FtpWebRequest ftp = GetRequest(ftpURI);
                ftp.Method = WebRequestMethods.Ftp.ListDirectory;
                ftp.Timeout = 3000;
                FtpWebResponse ftpResponse = (FtpWebResponse)ftp.GetResponse();
                ftpResponse.Close();
                return true;
            }
            catch 
            {
                return false;
            }
        }
       
        /// <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();
                    Console.WriteLine($@"FtpHelper.{method}:执行成功");
                    return true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行失败:\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
                {
                   Console.WriteLine($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行成功");                
                    return func();
                }
                catch (Exception ex)
                {
                     Console.WriteLine($@"FtpHelper({ftpHostIP},{username},{password}).{method}:执行失败 \r\n{ex}");
                    return default(T);
                }
            }
            else
            {
                return default(T);
            }
        }
        //根据服务器信息FtpWebRequest创建类的对象
        private FtpWebRequest GetRequest(string URI)
        {          
            FtpWebRequest result = (FtpWebRequest)WebRequest.Create(new Uri(URI));
            result.Credentials = new NetworkCredential(username, password);
            result.KeepAlive = true;
            //result.UsePassive = false;
            //result.UseBinary = false;
            return result;
        }

        /// <summary> 上传文件</summary>
        /// <param name="localFilePath">需要上传的文件全路径</param>
        /// <param name="remoteDir">需要上传到的目标目录下</param>
        public bool UploadFile(string localFilePath, string remoteDir = "")
        {
            FileInfo fileInfo = new FileInfo(localFilePath);
            if (remoteDir != "") CreateDir(remoteDir);//检查文件目录,不存在就自动创建
            string uri = Path.Combine(ftpURI, remoteDir, fileInfo.Name);
            return MethodInvoke($@"uploadFile({localFilePath},{remoteDir})", () =>
            {
                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="remoteDirName">目标目录</param>
        public void UploadDirectory(string localDir, string remoteDir = "")
        {
            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);
            //复制到的ftp服务器具体路径
            string newDir = remoteDir+"/"+ localDirName;
            //E:\504\UATS\UATS\bin\Debug\Library
            MethodInvoke($@"UploadAllFile({localDir},{remoteDir})", () =>
            {
                CreateDir(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)
                {
                    UploadDirectory(Path.Combine(localDir, dir.Name), newDir);
                }
            });
        }

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

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

        /// <summary> 删除目录或者其目录下所有的文件 </summary>
        /// <param name="remoteDir">目录名称</param>   
        public void DeleteDirAll(string remoteDir)
        {
            MethodInvoke($@"DeleteAll({remoteDir})", () =>
             {
                 List<ActFile> files = GetRemoteFiles(remoteDir);
                 foreach(var f in files)
                 {
                     if(f.isDir)
                     {
                         DeleteDirAll(remoteDir + "/" + f.name);
                         DeleteDir(remoteDir + "/" + f.name);
                         DeleteDir(remoteDir);
                     }
                     else
                     {
                         DeleteFile(remoteDir + "/" + f.name);
                     }
                 }
             }
            );
        }

        /// <summary>
        /// 下载单个文件
        /// </summary>
        /// <param name="remoteFilePath">从ftp要下载的文件全路径</param>
        /// <param name="localDir">下载至的本地路径</param>
        public bool DownloadFile(string remoteFilePath, string localDir)
        {
            string filename = remoteFilePath.Substring(remoteFilePath.LastIndexOf("/") + 1);
            string tmpname = Guid.NewGuid().ToString();
            string uri = Path.Combine(ftpURI, remoteFilePath);
            return MethodInvoke($@"DownloadFile({remoteFilePath},{localDir},{filename})", () =>
            {
                if (!Directory.Exists(localDir)) Directory.CreateDirectory(localDir);
                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(localDir, filename), FileMode.CreateNew))
                        {
                            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="remoteDir">FTP文件夹路径</param>    
        /// <param name="localDir">下载到的的本地文件夹路径</param>    
        public void DownloadAllFile(string remoteDir, string localDir)
        {
            MethodInvoke($@"DownloadAllFile({remoteDir},{localDir})", () =>
            {
                List<ActFile> files = GetRemoteFiles(remoteDir);
                if (!Directory.Exists(localDir))
                {
                    Directory.CreateDirectory(localDir);
                }
                foreach (var f in files)
                {
                    if (f.isDir) //文件夹,递归查询  
                    {
                        DownloadAllFile(remoteDir +"/"+f.name, Path.Combine(localDir, f.name));
                    }
                    else //文件,直接下载  
                    {
                        DownloadFile(remoteDir + "/" + f.name, localDir);
                    }
                }
            });
        }

        /// <summary>
        /// 获取当前目录下的目录及文件
        /// </summary>
        public List<ActFile> GetRemoteFiles(string remoteDir)
        {
            var ftpfileList = new List<ActFile>();
            string uri = Path.Combine(ftpURI, remoteDir);
            return MethodInvoke($@"GetFtpFile({remoteDir})", () =>
            {
                var a = new List<List<string>>();
                //FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI));
                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))
                    {
                        switch (FtpApp)
                        {
                            case FtpServerApp.FileZilla:
                                ftpfileList.Add(new ActFile
                                {
                                    isDir = line.StartsWith("d"),
                                    name = line.Substring(49).Trim(),
                                    path = remoteDir
                                });
                                break;
                            case FtpServerApp.IIS:
                                ftpfileList.Add(new ActFile
                                {
                                    isDir = line.IndexOf("<DIR>") > -1,
                                    name = line.Substring(39).Trim(),
                                    path = Path.Combine(remoteDir, line.Substring(39).Trim())
                                });
                                break;
                            case FtpServerApp.Unknown:
                            default:
                                break;
                        }
                        line = sr.ReadLine();
                    }
                    sr.Close();
                }
                return ftpfileList;
            });


        }

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

        /// <summary>
        /// 检查目录是否存在
        /// </summary>
        /// <param name="dirName"></param>
        /// <param name="remoteParentDir"></param>
        /// <returns></returns>
        public bool ExistDir(string dirName, string remoteParentDir = "")
        {
            string uri = ftpURI+remoteParentDir;
            return MethodInvoke($@"CheckDir({dirName}{remoteParentDir})", () =>
            {
                FtpWebRequest ftp = GetRequest(uri);
                ftp.UseBinary = true;
                ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
                WebResponse response = ftp.GetResponse();


                //Stream stream = ftp.GetResponse().GetResponseStream();
                Stream stream =response.GetResponseStream();
                using (StreamReader sr = new StreamReader(stream))
                {
                    string line = sr.ReadLine();
                    while (!string.IsNullOrEmpty(line))
                    {
                        switch (FtpApp)
                        {
                            case FtpServerApp.FileZilla:
                                if (line.StartsWith("d"))
                                {
                                    if (line.Substring(49).Trim() == dirName)
                                        return true;
                                }
                                break;
                            case FtpServerApp.IIS:
                                if (line.IndexOf("<DIR>") > -1)
                                {
                                    if (line.Substring(39).Trim() == dirName)
                                        return true;
                                }
                                break;
                            case FtpServerApp.Unknown:
                            default:
                                break;
                        }
                        
                        line = sr.ReadLine();
                    }
                    sr.Close();
                }
                stream.Close();
                return false;
            });

        }

        /// <summary>
        /// 在ftp服务器上创建指定目录,父目录不存在则创建
        /// </summary>
        /// <param name="remoteDir">要创建的指定目录</param>
        /// <returns></returns>
        public bool CreateDir(string remoteDir)
        {
            var dirs = remoteDir.Split('/').ToList();//针对多级目录分割
            string currentDir = string.Empty;
            return MethodInvoke($@"MakeDir({remoteDir})", () =>
            {
                foreach (var dir in dirs)
                {
                    if (!ExistDir(dir, currentDir))//检查目录不存在则创建
                    {
                        currentDir += (currentDir.EndsWith("/")? "": "/") + dir;
                        string uri = ftpURI+currentDir;
                        FtpWebRequest ftp = GetRequest(uri);
                        ftp.Method = WebRequestMethods.Ftp.MakeDirectory;
                        FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
                        response.Close();
                    }
                    else
                    {
                        currentDir += (currentDir.EndsWith("/") ? "" : "/") + dir;
                    }
                }
            });
        }

        /// <summary>文件重命名 </summary>
        /// <param name="currentFilename">当前名称</param>
        /// <param name="newFilename">重命名名称</param>
        /// <param name="remoteDir">所在的目录</param>
        public bool Rename(string currentFilename, string newFilename, string remoteDir = "")
        {
            string uri = Path.Combine(ftpURI, remoteDir, currentFilename);
            return MethodInvoke($@"Rename({currentFilename},{newFilename},{remoteDir})", () =>
            {
                FtpWebRequest ftp = GetRequest(uri);
                ftp.Method = WebRequestMethods.Ftp.Rename;
                ftp.RenameTo = newFilename;
                FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
                response.Close();
            });
        }
    }
    /// <summary>
    /// ftp服务器软件
    /// </summary>
    public enum FtpServerApp
    {
        Unknown = 0,
        IIS = 1,
        FileZilla = 2
    }
    /// <summary>
    /// 文件(夹)信息
    /// </summary>
    public class ActFile
    {
        public int level { get; set; } = 0;
        //真则是文件夹(否则为文件)
        public bool isDir { get; set; }
        public string name { get; set; }
        public string path
        {
            get; set;
        }
    }

调用

        public static FtpHelper CreateFtpHelper()
        {
            try
            {
                IPAddress ip;
                if (!IPAddress.TryParse(FtpServerIP, out ip))
                {
                    throw new Exception("未能建立与ftp服务器的连接,未设置合法的ftp服务器IP地址。");
                }
                FtpHelper ftpHelper = new FtpHelper(FtpServerIP, FtpUserID, FtpPassword);

                if (ftpHelper.checkConnect())
                {
                    ftpHelper.FtpApp = (FtpServerApp)Enum.Parse(typeof(FtpServerApp), FtpServerApp);
                    return ftpHelper;
                }
                throw new Exception("未能建立与ftp服务器的连接,可能是由于服务器端口21未打开或被占用。");
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }
        //然后就可以使用这个FtpHelper对象调不同方法了(●'◡'●)

备注

1.本地路径拼接使用反斜杠,但考虑转义字符的影响,代码中使用"\"或@“\”或Path.Combine(localDir, f.name);
2.服务器路径拼接使用斜杠即可“/”;
3.上述代码支持ftpServer软件:windows自带IIS或FileZilla,本人推荐后者,教程转至使用Filezilla Server配置FTP服务器,配置时注意勾选权限。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个基于C#FTP上传帮助示例: ```csharp using System; using System.IO; using System.Net; public class FtpHelper { private string ftpServerIP; private string ftpUserID; private string ftpPassword; private FtpWebRequest reqFTP; public FtpHelper(string ftpServerIP, string ftpUserID, string ftpPassword) { this.ftpServerIP = ftpServerIP; this.ftpUserID = ftpUserID; this.ftpPassword = ftpPassword; } // 上传文件 public bool Upload(string localFilePath, string remoteFileName) { FileInfo fileInfo = new FileInfo(localFilePath); string uri = "ftp://" + ftpServerIP + "/" + remoteFileName; reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); reqFTP.KeepAlive = false; reqFTP.Method = WebRequestMethods.Ftp.UploadFile; reqFTP.UseBinary = true; reqFTP.ContentLength = fileInfo.Length; int buffLength = 2048; byte[] buff = new byte[buffLength]; int contentLen; using (FileStream fs = fileInfo.OpenRead()) { using (Stream strm = reqFTP.GetRequestStream()) { contentLen = fs.Read(buff, 0, buffLength); while (contentLen != 0) { strm.Write(buff, 0, contentLen); contentLen = fs.Read(buff, 0, buffLength); } } } FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); response.Close(); return true; } } ``` 使用方法: ```csharp string localFilePath = @"C:\test.txt"; string remoteFileName = "test.txt"; string ftpServerIP = "ftp://192.168.1.1"; string ftpUserID = "username"; string ftpPassword = "password"; FtpHelper ftpHelper = new FtpHelper(ftpServerIP, ftpUserID, ftpPassword); ftpHelper.Upload(localFilePath, remoteFileName); ``` 其中,`localFilePath`为本地文件路径,`remoteFileName`为远程文件名,`ftpServerIP`为FTP服务器地址,`ftpUserID`和`ftpPassword`为FTP登录凭据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值