当前位置: 首页 > backend >正文

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

1. 核心技术原理

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

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

2. 关键类组件说明

FtpClient类结构
- 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服务器配置
# 确保FTP服务运行
sudo service vsftpd status# 配置文件权限
chmod 755 /ftp/directory
chown ftpuser:ftpgroup /ftp/directory
防火墙设置
  • 开放21端口(控制连接)
  • 配置被动模式端口范围

9. 扩展建议

  1. 异步操作:对于大文件,考虑使用异步方法
  2. 进度报告:添加传输进度回调
  3. 断点续传:实现REST命令支持
  4. 连接池:频繁操作时维护连接池
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秒超时// 缓冲区大小设置为2KBint 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();}}
}
http://www.xdnf.cn/news/19512.html

相关文章:

  • 【云存储桶安全】怎么满足业务需求,又最大程度上满足信息安全要求呢?
  • 构建深度学习音频识别模型:从数据预处理到性能评估
  • 【K8s】整体认识K8s之监控与升级/ETCD的备份和恢复/kustomization/CRD
  • wpf之样式
  • PAT 1089 Insert or Merge
  • UBUNTU之Onvif开源服务器onvif_srvd:1、编译
  • 如何使用VMware创建一台Ubuntu机器
  • Shell脚本实用技巧集锦:从时间判断到系统监控
  • 【数据可视化-104】安徽省2025年上半年GDP数据可视化分析:用Python和Pyecharts打造炫酷大屏
  • HTTP/2 多路复用
  • 网络流量分析——熟悉Wireshark
  • 时序数据库国产的有哪些?
  • ​​--flush-logs 的作用:刷新 MySQL 的日志文件(主要是二进制日志 binlog)​
  • 解析简历重难点与面试回答要点
  • 【开题答辩全过程】以 健身爱好者饮食管理小程序为例,包含答辩的问题和答案
  • LeetCode82删除排序链表中的重复元素 II
  • 力扣hot100 | 堆 | 215. 数组中的第K个最大元素、347. 前 K 个高频元素、128. 最长连续序列
  • 《架构师手记:SpringCloud整合Nacos实战·一》
  • Transformer的并行计算与长序列处理瓶颈总结
  • 可编辑115页PPT | 某纸制品制造企业数字化转型战略规划项目建议书
  • 【实验protocol分享】了解流式细胞术
  • 串口通讯个人见解
  • 软考中级【网络工程师】第6版教材 第4章 无线通信网 (下)
  • matlab扫雷小游戏
  • 艾莉丝努力练剑的创作纪念日:星河初启,牧梦长空
  • 企业级主流日志系统架构对比ELKK Stack -Grafana Stack
  • pyside6小项目:进制转换器
  • 【OpenFeign】基础使用
  • Kubernetes一网络组件概述
  • Java比较器