基于.NET Framework 4.0的FTP文件传输类

1. 核心技术原理

这个FTP客户端基于.NET Framework 4.0的System.Net命名空间,主要使用了:

  • FtpWebRequest:用于创建FTP请求
  • FtpWebResponse:接收FTP服务器响应
  • NetworkCredential:处理身份验证

2. 关键类组件说明

FtpClient类结构
csharp 复制代码
- ftpServerIP: FTP服务器IP地址
- ftpUserID: 登录用户名
- ftpPassword: 登录密码
- ftpPort: FTP端口(默认21)

3. 核心功能详解

上传文件 (UploadFile)
复制代码
工作流程:
1. 构建FTP URI路径
2. 创建FtpWebRequest并设置为上传模式
3. 使用FileStream读取本地文件
4. 通过缓冲区分块传输数据
5. 完成后关闭所有流

关键设置:

  • UseBinary = true:使用二进制模式,确保文件完整性
  • KeepAlive = false:每次请求后关闭连接,避免超时
  • ContentLength:设置文件大小,让服务器知道传输量
  • 缓冲区2KB:平衡内存使用和传输效率
下载文件 (DownloadFile)
复制代码
工作流程:
1. 创建下载请求
2. 获取服务器响应流
3. 创建本地文件(自动创建目录)
4. 分块读取并写入本地文件
5. 关闭所有资源

4. Linux兼容性考虑

  • 路径分隔符 :Linux使用/,代码中远程路径使用正斜杠
  • 权限处理:确保FTP用户在Linux上有相应的读写权限
  • 编码问题:使用UTF-8编码处理文件名,支持中文
  • 二进制模式:避免Windows/Linux换行符差异

5. 错误处理机制

每个方法都包含完整的异常处理:

  • try-catch-finally结构确保资源释放
  • 返回布尔值表示操作成功/失败
  • 控制台输出错误信息便于调试

6. 性能优化要点

  1. 缓冲区大小:2KB适合大多数场景,可根据网络状况调整
  2. 超时设置:30秒超时避免长时间等待
  3. KeepAlive=false:避免连接池问题
  4. 资源管理:finally块确保流正确关闭

7. 安全性建议

  1. 加密传输:考虑使用FTPS(FTP over SSL)
  2. 凭据保护:不要硬编码密码,使用配置文件或加密存储
  3. 输入验证:验证文件路径防止路径遍历攻击
  4. 错误信息:生产环境避免暴露详细错误信息

8. 使用注意事项

Linux服务器配置
bash 复制代码
# 确保FTP服务运行
sudo service vsftpd status

# 配置文件权限
chmod 755 /ftp/directory
chown ftpuser:ftpgroup /ftp/directory
防火墙设置
  • 开放21端口(控制连接)
  • 配置被动模式端口范围

9. 扩展建议

  1. 异步操作:对于大文件,考虑使用异步方法
  2. 进度报告:添加传输进度回调
  3. 断点续传:实现REST命令支持
  4. 连接池:频繁操作时维护连接池
csharp 复制代码
using System;
using System.IO;
using System.Net;
using System.Text;

namespace FtpFileTransfer
{
    /// <summary>
    /// FTP文件传输类,用于向Linux设备上传下载文件
    /// </summary>
    public class FtpClient
    {
        private string ftpServerIP;
        private string ftpUserID;
        private string ftpPassword;
        private int ftpPort;
        
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="serverIP">FTP服务器IP地址</param>
        /// <param name="userID">用户名</param>
        /// <param name="password">密码</param>
        /// <param name="port">端口号(默认21)</param>
        public FtpClient(string serverIP, string userID, string password, int port = 21)
        {
            this.ftpServerIP = serverIP;
            this.ftpUserID = userID;
            this.ftpPassword = password;
            this.ftpPort = port;
        }
        
        /// <summary>
        /// 上传文件到FTP服务器
        /// </summary>
        /// <param name="localFilePath">本地文件完整路径</param>
        /// <param name="remoteFileName">远程文件名(包含路径)</param>
        /// <returns>上传是否成功</returns>
        public bool UploadFile(string localFilePath, string remoteFileName)
        {
            FileInfo fileInfo = new FileInfo(localFilePath);
            string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, remoteFileName);
            
            FtpWebRequest request = null;
            FileStream fs = null;
            Stream requestStream = null;
            
            try
            {
                // 创建FTP请求
                request = (FtpWebRequest)WebRequest.Create(new Uri(uri));
                request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                request.KeepAlive = false;
                request.Method = WebRequestMethods.Ftp.UploadFile;
                request.UseBinary = true;  // 二进制模式传输
                request.ContentLength = fileInfo.Length;
                request.Timeout = 30000;  // 30秒超时
                
                // 缓冲区大小设置为2KB
                int buffLength = 2048;
                byte[] buff = new byte[buffLength];
                int contentLen;
                
                // 打开本地文件流
                fs = fileInfo.OpenRead();
                
                // 获取FTP请求流
                requestStream = request.GetRequestStream();
                
                // 读取文件并写入FTP流
                contentLen = fs.Read(buff, 0, buffLength);
                while (contentLen != 0)
                {
                    requestStream.Write(buff, 0, contentLen);
                    contentLen = fs.Read(buff, 0, buffLength);
                }
                
                Console.WriteLine("文件 {0} 上传成功", fileInfo.Name);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine("上传文件时发生错误: " + ex.Message);
                return false;
            }
            finally
            {
                // 关闭流
                if (requestStream != null)
                    requestStream.Close();
                if (fs != null)
                    fs.Close();
                if (request != null)
                    request.Abort();
            }
        }
        
        /// <summary>
        /// 从FTP服务器下载文件
        /// </summary>
        /// <param name="remoteFileName">远程文件名(包含路径)</param>
        /// <param name="localFilePath">本地保存路径</param>
        /// <returns>下载是否成功</returns>
        public bool DownloadFile(string remoteFileName, string localFilePath)
        {
            string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, remoteFileName);
            
            FtpWebRequest request = null;
            FtpWebResponse response = null;
            Stream responseStream = null;
            FileStream outputStream = null;
            
            try
            {
                // 创建FTP请求
                request = (FtpWebRequest)WebRequest.Create(new Uri(uri));
                request.Method = WebRequestMethods.Ftp.DownloadFile;
                request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                request.UseBinary = true;
                request.KeepAlive = false;
                request.Timeout = 30000;
                
                // 获取响应
                response = (FtpWebResponse)request.GetResponse();
                responseStream = response.GetResponseStream();
                
                // 创建本地文件
                string directoryPath = Path.GetDirectoryName(localFilePath);
                if (!Directory.Exists(directoryPath))
                {
                    Directory.CreateDirectory(directoryPath);
                }
                
                outputStream = new FileStream(localFilePath, FileMode.Create);
                
                // 缓冲区
                byte[] buffer = new byte[2048];
                int readCount = responseStream.Read(buffer, 0, buffer.Length);
                
                // 读取并写入文件
                while (readCount > 0)
                {
                    outputStream.Write(buffer, 0, readCount);
                    readCount = responseStream.Read(buffer, 0, buffer.Length);
                }
                
                Console.WriteLine("文件下载成功,保存到: {0}", localFilePath);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine("下载文件时发生错误: " + ex.Message);
                return false;
            }
            finally
            {
                // 关闭流和响应
                if (outputStream != null)
                    outputStream.Close();
                if (responseStream != null)
                    responseStream.Close();
                if (response != null)
                    response.Close();
                if (request != null)
                    request.Abort();
            }
        }
        
        /// <summary>
        /// 获取FTP服务器上的文件列表
        /// </summary>
        /// <param name="remotePath">远程路径</param>
        /// <returns>文件列表</returns>
        public string[] GetFileList(string remotePath)
        {
            string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, remotePath);
            
            try
            {
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(uri));
                request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                request.Method = WebRequestMethods.Ftp.ListDirectory;
                request.KeepAlive = false;
                
                FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                
                string line = reader.ReadLine();
                StringBuilder result = new StringBuilder();
                
                while (line != null)
                {
                    result.Append(line);
                    result.Append("\n");
                    line = reader.ReadLine();
                }
                
                reader.Close();
                response.Close();
                
                if (result.Length > 0)
                {
                    result.Remove(result.ToString().LastIndexOf('\n'), 1);
                    return result.ToString().Split('\n');
                }
                else
                {
                    return new string[] { };
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("获取文件列表时发生错误: " + ex.Message);
                return new string[] { };
            }
        }
        
        /// <summary>
        /// 删除FTP服务器上的文件
        /// </summary>
        /// <param name="remoteFileName">远程文件名</param>
        /// <returns>删除是否成功</returns>
        public bool DeleteFile(string remoteFileName)
        {
            string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, remoteFileName);
            
            try
            {
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(uri));
                request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                request.Method = WebRequestMethods.Ftp.DeleteFile;
                request.KeepAlive = false;
                
                FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                response.Close();
                
                Console.WriteLine("文件 {0} 删除成功", remoteFileName);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine("删除文件时发生错误: " + ex.Message);
                return false;
            }
        }
        
        /// <summary>
        /// 创建FTP服务器上的目录
        /// </summary>
        /// <param name="directoryName">目录名</param>
        /// <returns>创建是否成功</returns>
        public bool CreateDirectory(string directoryName)
        {
            string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, directoryName);
            
            try
            {
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(uri));
                request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                request.Method = WebRequestMethods.Ftp.MakeDirectory;
                request.KeepAlive = false;
                
                FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                response.Close();
                
                Console.WriteLine("目录 {0} 创建成功", directoryName);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine("创建目录时发生错误: " + ex.Message);
                return false;
            }
        }
        
        /// <summary>
        /// 检查文件是否存在
        /// </summary>
        /// <param name="remoteFileName">远程文件名</param>
        /// <returns>文件是否存在</returns>
        public bool FileExists(string remoteFileName)
        {
            string uri = string.Format("ftp://{0}:{1}/{2}", ftpServerIP, ftpPort, remoteFileName);
            
            try
            {
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(uri));
                request.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                request.Method = WebRequestMethods.Ftp.GetFileSize;
                request.KeepAlive = false;
                
                FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                response.Close();
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
    
    /// <summary>
    /// 使用示例
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            // 创建FTP客户端实例
            FtpClient ftpClient = new FtpClient(
                "192.168.1.100",  // Linux服务器IP
                "username",        // FTP用户名
                "password",        // FTP密码
                21                 // FTP端口(默认21)
            );
            
            // 上传文件示例
            bool uploadResult = ftpClient.UploadFile(
                @"C:\local\test.txt",           // 本地文件路径
                "/remote/path/test.txt"          // 远程文件路径
            );
            
            // 下载文件示例
            bool downloadResult = ftpClient.DownloadFile(
                "/remote/path/test.txt",        // 远程文件路径
                @"C:\download\test.txt"          // 本地保存路径
            );
            
            // 获取文件列表
            string[] files = ftpClient.GetFileList("/remote/path/");
            foreach (string file in files)
            {
                Console.WriteLine("文件: " + file);
            }
            
            // 检查文件是否存在
            bool exists = ftpClient.FileExists("/remote/path/test.txt");
            Console.WriteLine("文件存在: " + exists);
            
            // 创建目录
            ftpClient.CreateDirectory("/remote/newdir");
            
            // 删除文件
            ftpClient.DeleteFile("/remote/path/old.txt");
            
            Console.ReadLine();
        }
    }
}
相关推荐
MasterNeverDown12 小时前
.NET 微服务日志系统:Serilog + Loki + Grafana 实践指南
微服务·.net·grafana
界面开发小八哥13 小时前
DevExpress WinForms中文教程:Data Grid - 过滤编辑器
人工智能·ui·.net·devexpress·用户界面·winforms
追逐时光者1 天前
C#/.NET/.NET Core技术前沿周刊 | 第 52 期(2025年8.25-8.31)
后端·.net
唐青枫1 天前
从 Skip Take 到 Keyset:C# 分页原理与实践
c#·.net
喵叔哟2 天前
49.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--扩展功能--集成网关--Refit跨服务调用
微服务·架构·.net
专注VB编程开发20年2 天前
C# .NET支持多线程并发的压缩组件
开发语言·前端·c#·.net·多线程·zip·压缩
界面开发小八哥3 天前
DevExpress WPF中文教程:如何将WPF数据网格绑定到本地集合?
.net·wpf·界面控件·devexpress·ui开发
界面开发小八哥3 天前
DevExpress WinForms中文教程:Data Grid - Excel样式的自定义过滤器对话框
ui·.net·excel·界面控件·winform·devexpress·ui开发