发布于2026-07-23 阅读(0)
扫一扫,手机访问
实现FTP上传,通常会遇到两种选择:一种是直接拿系统自带的方法手搓,另一种是借助现成的第三方库。两种方案各有长短,下面就来拆解一下。
方案一:自己动手,用系统方法实现。好处是无需额外依赖,想怎么折腾都行,灵活性拉满;坏处也很明显——代码量大,各种边界情况都得自己处理,稍微不留神就会踩坑。
方案二:用开源的 Nuget 包 FluentFTP。上手快、用起来顺手,功能也相当丰富;代价就是项目中多了一个依赖项。
////// ftp传输 /// /// ftp保存地址 例:ftp://172.18.18.53/172.18.18.101/ /// ftp保存文件名称 例:htrs_1.mp4 /// 本地文件路径 例:C:\files\htrs_1.mp4 /// ftp用户名 /// ftp密码 public static bool FTPUploadFile(string ftpSa vePath, string ftpFileName, string localFilePath, string userName, string password) { if (!File.Exists(localFilePath)) { return false; } //校验路径是否存在 if (!TryCreateDirectory(ftpSa vePath, userName, password)) return false; try { FileInfo fileInfo = new FileInfo(localFilePath); // 创建ftp请求 FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpSa vePath + ftpFileName); request.Method = WebRequestMethods.Ftp.UploadFile; request.Credentials = new NetworkCredential(userName, password); request.UseBinary = true; request.KeepAlive = false; // 上传完成后关闭连接 request.Timeout = 300000; // 5分钟超时 // ✅ 使用流式传输,避免内存溢出 using (FileStream fileStream = new FileStream(localFilePath, FileMode.Open, FileAccess.Read)) using (Stream requestStream = request.GetRequestStream()) { byte[] buffer = new byte[128 * 1024]; // 64KB缓冲区 int bytesRead; long totalBytes = 0; DateTime lastLogTime = DateTime.Now; while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0) { requestStream.Write(buffer, 0, bytesRead); totalBytes += bytesRead; // 每10秒记录一次上传进度(可选) if ((DateTime.Now - lastLogTime).TotalSeconds >= 10) { double progress = (double)totalBytes / fileInfo.Length * 100; lastLogTime = DateTime.Now; } } } } catch (Exception ex) { return false; } return true; } ////// 校验ftp目录是否存在 /// /// /// /// ///public static bool TryCreateDirectory(string directoryUri, string username, string password) { try { // 创建 FTP 请求以检查目录 FtpWebRequest request = (FtpWebRequest)WebRequest.Create(directoryUri); request.Method = WebRequestMethods.Ftp.ListDirectory; request.Credentials = new NetworkCredential(username, password); // 尝试获取目录列表 using FtpWebResponse response = (FtpWebResponse)request.GetResponse(); } catch (WebException ex) { // 如果目录不存在,则会抛出异常 if (ex.Response is FtpWebResponse response && response.StatusCode == FtpStatusCode.ActionNotTakenFileUna vailable) { // 创建目录 FtpWebRequest createDirRequest = (FtpWebRequest)WebRequest.Create(directoryUri); createDirRequest.Method = WebRequestMethods.Ftp.MakeDirectory; createDirRequest.Credentials = new NetworkCredential(username, password); using var createResponse = (FtpWebResponse)createDirRequest.GetResponse(); } else { //其他异常 return false; } } catch (Exception ex) { return false; } return true; }
手动实现的代码量不小,但关键点在于流式传输和超时控制,以及目录的自动创建。如果想要更省心,不妨试试下面这个方案。
public async Task Test()
{
string ip = "172.18.18.200";
int port = 21;
string userName = "ftpuser";
string pwd = "ftpuser";
FluentFTP.AsyncFtpClient ftp = new FluentFTP.AsyncFtpClient(ip, userName, pwd, port)
{
Config = new FluentFTP.FtpConfig
{
ConnectTimeout = 5000, //连接超时,单位为毫秒
DataConnectionConnectTimeout = 5000, //数据连接超时,单位为毫秒
DataConnectionReadTimeout = 5000, //数据读取超时,单位为毫秒
ReadTimeout = 5000, //读取超时,单位为毫秒
RetryAttempts = 3 //重试次数
}
};
//开始连接FTP服务器
await ftp.Connect();
// 检查目录是否存在,如果不存在则创建
if (! await ftp.DirectoryExists("wtTest"))
{
await ftp.CreateDirectory("wtTest");
}
// 上传文件
await ftp.UploadFile(@"C:\Users\Htkw\Desktop\111\1.jpg", "wtTest/test.jpg");
// 下载文件
await ftp.DownloadFile(@"C:\Users\Htkw\Desktop\111\downloaded_test.jpg", "wtTest/test.jpg");
await ftp.Disconnect(); //关闭连接
await ftp.DisposeAsync(); //释放资源
}
用 FluentFTP 写起来就清爽多了:连接、检查目录、上传、下载,几行代码搞定。而且它还内置了重试、超时等机制,省去了不少手动异常处理的功夫。如果你正在做一个需要稳定 FTP 交互的项目,这个库值得一试。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8