基于.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. 性能优化要点
- 缓冲区大小:2KB适合大多数场景,可根据网络状况调整
- 超时设置:30秒超时避免长时间等待
- KeepAlive=false:避免连接池问题
- 资源管理:finally块确保流正确关闭
7. 安全性建议
- 加密传输:考虑使用FTPS(FTP over SSL)
- 凭据保护:不要硬编码密码,使用配置文件或加密存储
- 输入验证:验证文件路径防止路径遍历攻击
- 错误信息:生产环境避免暴露详细错误信息
8. 使用注意事项
Linux服务器配置
# 确保FTP服务运行
sudo service vsftpd status# 配置文件权限
chmod 755 /ftp/directory
chown ftpuser:ftpgroup /ftp/directory
防火墙设置
- 开放21端口(控制连接)
- 配置被动模式端口范围
9. 扩展建议
- 异步操作:对于大文件,考虑使用异步方法
- 进度报告:添加传输进度回调
- 断点续传:实现REST命令支持
- 连接池:频繁操作时维护连接池
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();}}
}