C# FTP调用代码实现

1. 使用 .NET 自带 FtpWebRequest 实现 FTP 操作

1.1 文件上传

using System.Net;
using System.IO;

public void UploadFile(string ftpUrl, string username, string password, string localFile, string remoteFile)
{
    string url = $"{ftpUrl}/{remoteFile}";
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
    request.Method = WebRequestMethods.Ftp.UploadFile;
    request.Credentials = new NetworkCredential(username, password);

    byte[] fileContents = File.ReadAllBytes(localFile);
    request.ContentLength = fileContents.Length;

    using (Stream requestStream = request.GetRequestStream())
    {
        requestStream.Write(fileContents, 0, fileContents.Length);
    }
    using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
    {
        Console.WriteLine($"上传状态: {response.StatusDescription}");
    }
}

1.2 文件下载

public void DownloadFile(string ftpUrl, string username, string password, string remoteFile, string localFile)
{
    string url = $"{ftpUrl}/{remoteFile}";
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
    request.Method = WebRequestMethods.Ftp.DownloadFile;
    request.Credentials = new NetworkCredential(username, password);

    using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
    using (Stream responseStream = response.GetResponseStream())
    using (FileStream fs = new FileStream(localFile, FileMode.Create))
    {
        responseStream.CopyTo(fs);
    }
}

1.3 列出目录和文件

public void ListDirectory(string ftpUrl, string username, string password)
{
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpUrl);
    request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
    request.Credentials = new NetworkCredential(username, password);

    using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
    using (Stream responseStream = response.GetResponseStream())
    using (StreamReader reader = new StreamReader(responseStream))
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            Console.WriteLine(line);
        }
    }
}

1.4 删除文件和目录

public void DeleteFile(string ftpUrl, string username, string password, string remoteFile)
{
    string url = $"{ftpUrl}/{remoteFile}";
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
    request.Method = WebRequestMethods.Ftp.DeleteFile;
    request.Credentials = new NetworkCredential(username, password);

    using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
    {
        Console.WriteLine($"删除状态: {response.StatusDescription}");
    }
}

public void DeleteDirectory(string ftpUrl, string username, string password, string remoteDir)
{
    string url = $"{ftpUrl}/{remoteDir}";
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
    request.Method = WebRequestMethods.Ftp.RemoveDirectory;
    request.Credentials = new NetworkCredential(username, password);

    using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
    {
        Console.WriteLine($"删除目录状态: {response.StatusDescription}");
    }
}

2. 进阶:断点续传(部分实现)

.NET标准库不直接支持FTP断点续传,但可以通过设置 ContentOffset 实现下载断点续传

public void ResumeDownloadFile(string ftpUrl, string username, string password, string remoteFile, string localFile)
{
    long offset = new FileInfo(localFile).Length;
    string url = $"{ftpUrl}/{remoteFile}";
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
    request.Method = WebRequestMethods.Ftp.DownloadFile;
    request.Credentials = new NetworkCredential(username, password);
    request.ContentOffset = offset;

    using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
    using (Stream responseStream = response.GetResponseStream())
    using (FileStream fs = new FileStream(localFile, FileMode.Append))
    {
        responseStream.CopyTo(fs);
    }
}

3. 异常处理建议

try
{
    // FTP操作
}
catch (WebException ex)
{
    if (ex.Response is FtpWebResponse ftpResponse)
    {
        Console.WriteLine($"FTP响应: {ftpResponse.StatusDescription}");
    }
    else
    {
        Console.WriteLine($"网络异常: {ex.Message}");
    }
}
catch (Exception ex)
{
    Console.WriteLine($"其他异常: {ex.Message}");
}

4. 推荐:使用 FluentFTP 第三方库(更强大)

NuGet 安装:
Install-Package FluentFTP

示例代码:

using FluentFTP;

public void FluentFtpUpload(string host, string user, string pass, string localFile, string remoteFile)
{
    var client = new FtpClient(host, user, pass);
    client.Connect();
    client.UploadFile(localFile, remoteFile, FtpExists.Overwrite, true, FtpVerify.Retry);
    client.Disconnect();
}

FluentFTP 支持断点续传、批量操作、进度回调、SFTP等,API更现代,推荐生产环境使用。


5. 常见问题与建议

  • 推荐使用被动模式,防火墙友好:request.UsePassive = true;
  • FTP明文传输不安全,敏感业务建议用 SFTP/FTPS
  • 及时关闭连接和流,防止资源泄漏
  • 大文件建议分块/断点续传,提升健壮性
  • 批量操作建议用多线程或异步(FluentFTP支持)

6. 批量上传/下载(FluentFTP 推荐)

批量上传

using FluentFTP;

public void BatchUpload(string host, string user, string pass, string localDir, string remoteDir)
{
    var client = new FtpClient(host, user, pass);
    client.Connect();
    foreach (var file in Directory.GetFiles(localDir))
    {
        client.UploadFile(file, $"{remoteDir}/{Path.GetFileName(file)}", FtpExists.Overwrite, true, FtpVerify.Retry);
    }
    client.Disconnect();
}

批量下载

public void BatchDownload(string host, string user, string pass, string remoteDir, string localDir)
{
    var client = new FtpClient(host, user, pass);
    client.Connect();
    foreach (var item in client.GetListing(remoteDir, FtpListOption.AllFiles))
    {
        if (item.Type == FtpFileSystemObjectType.File)
        {
            client.DownloadFile($"{localDir}\\{item.Name}", item.FullName, FtpLocalExists.Overwrite, FtpVerify.Retry);
        }
    }
    client.Disconnect();
}

7. 进度条与回调监听

FluentFTP 支持进度回调,非常适合大文件或批量传输场景。

client.UploadFile(localFile, remoteFile, FtpExists.Overwrite, true, FtpVerify.None, progress: new Progress<FtpProgress>(p => {
    Console.WriteLine($"已上传: {p.TransferredBytes}/{p.TotalBytes} ({p.Progress}% 完成)");
}));

8. 异步与多线程操作

FluentFTP 支持异步 API,可结合 async/await 实现高并发:

public async Task AsyncUpload(string host, string user, string pass, string localFile, string remoteFile)
{
    var client = new FtpClient(host, user, pass);
    await client.ConnectAsync();
    await client.UploadFileAsync(localFile, remoteFile, FtpExists.Overwrite, true, FtpVerify.None);
    await client.DisconnectAsync();
}

多线程批量传输建议用 Parallel.ForEach 或 Task.Run,结合异步API。


9. SFTP 实现(推荐 SSH.NET 库)

NuGet 安装:
Install-Package SSH.NET

上传/下载示例:

using Renci.SshNet;

public void SftpUpload(string host, string user, string pass, string localFile, string remoteFile)
{
    using (var sftp = new SftpClient(host, 22, user, pass))
    {
        sftp.Connect();
        using (var fs = new FileStream(localFile, FileMode.Open))
        {
            sftp.UploadFile(fs, remoteFile);
        }
        sftp.Disconnect();
    }
}

public void SftpDownload(string host, string user, string pass, string remoteFile, string localFile)
{
    using (var sftp = new SftpClient(host, 22, user, pass))
    {
        sftp.Connect();
        using (var fs = new FileStream(localFile, FileMode.Create))
        {
            sftp.DownloadFile(remoteFile, fs);
        }
        sftp.Disconnect();
    }
}

10. 健壮性与异常重试

int maxRetries = 3;
for (int i = 0; i < maxRetries; i++)
{
    try
    {
        // FTP/SFTP操作
        break;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"重试 {i+1} 次: {ex.Message}");
        if (i == maxRetries - 1) throw;
        Thread.Sleep(1000);
    }
}

11. 递归上传/下载目录

FTP递归上传(FluentFTP示例)

using FluentFTP;

public void UploadDirectoryRecursive(string host, string user, string pass, string localDir, string remoteDir)
{
    var client = new FtpClient(host, user, pass);
    client.Connect();
    client.UploadDirectory(localDir, remoteDir, FtpFolderSyncMode.Update, FtpRemoteExists.Overwrite, FtpVerify.None);
    client.Disconnect();
}

FTP递归下载

public void DownloadDirectoryRecursive(string host, string user, string pass, string remoteDir, string localDir)
{
    var client = new FtpClient(host, user, pass);
    client.Connect();
    client.DownloadDirectory(localDir, remoteDir, FtpFolderSyncMode.Update, FtpLocalExists.Overwrite, FtpVerify.None);
    client.Disconnect();
}

SFTP递归操作(SSH.NET

using Renci.SshNet;

public void SftpDownloadDirectory(string host, string user, string pass, string remoteDir, string localDir)
{
    using (var sftp = new SftpClient(host, 22, user, pass))
    {
        sftp.Connect();
        var files = sftp.ListDirectory(remoteDir);
        Directory.CreateDirectory(localDir);
        foreach (var file in files)
        {
            if (!file.Name.StartsWith("."))
            {
                string localPath = Path.Combine(localDir, file.Name);
                string remotePath = file.FullName;
                if (file.IsDirectory)
                {
                    SftpDownloadDirectory(host, user, pass, remotePath, localPath);
                }
                else
                {
                    using (var fs = new FileStream(localPath, FileMode.Create))
                    {
                        sftp.DownloadFile(remotePath, fs);
                    }
                }
            }
        }
        sftp.Disconnect();
    }
}

12. 断点续传(FluentFTP示例)

client.UploadFile(localFile, remoteFile, FtpExists.Resume, false, FtpVerify.Retry);
client.DownloadFile(localFile, remoteFile, FtpLocalExists.Resume, FtpVerify.Retry);

Resume模式会自动检测已上传/下载的字节数,断点续传。


13. 连接池设计建议

  • 对于高并发场景,建议用对象池(如自定义或结合 Microsoft.Extensions.ObjectPool)。
  • 每个线程/任务从池中借出连接,用完归还,避免频繁连接/断开。
  • FluentFTP和SSH.NET都可自定义连接池(实现 IDisposable,支持多线程)。

14. 跨平台兼容性

  • .NET Core/6/7 支持 FluentFTP、SSH.NET,可在 Windows/Linux/Mac 部署。
  • 文件路径注意区分 / 与 \,建议用 Path.Combine
  • 字符编码建议统一 UTF-8,避免中文乱码。

15. 日志与监控

  • FluentFTP支持事件监听,可记录每次上传/下载/异常。
  • 企业应用建议集成 Serilog/NLog/Log4Net 实现日志持久化与告警。
  • 可结合 Prometheus/Grafana 采集传输量、错误率等指标。

16. 安全加固建议

  • FTP传输建议启用 FTPS(SSL/TLS),或优先用 SFTP。
  • 密码、主机等敏感信息用配置中心或环境变量管理,不要硬编码。
  • 限制服务器端口、白名单IP,避免暴露在公网。
  • 定期更换账号密码,开启服务器日志审计。

17. 企业应用架构建议

  • 封装 FTP/SFTP 工具类或服务,业务代码只调用接口。
  • 支持批量任务、断点续传、自动重试、进度回调。
  • 结合定时任务/消息队列,实现大文件/多文件异步传输。
  • 日志与监控全链路覆盖,保证可运维、可追溯。

18. 面试进阶问题&答题思路

  1. 如何实现高可用的 FTP/SFTP 文件服务?

    • 多节点部署,连接池管理,自动重试,断点续传,监控告警。
  2. FTP/SFTP在分布式系统中的应用场景?

    • 跨系统文件同步、定时批量数据交换、异地备份、与微服务/大数据平台集成等。
  3. 如何应对大文件传输中的网络抖动和中断?

    • 断点续传、自动重连、分块传输、错误重试、传输进度保存。
  4. 如何保证FTP/SFTP服务的安全性和合规性?

    • 使用加密协议(FTPS/SFTP)、权限细分、日志审计、配置白名单。
  5. C# FTP/SFTP与Java实现有何异同?

    • API不同,原理一致;C#推荐FluentFTP/SSH.NET,Java推荐Commons Net/JSch。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猩火燎猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值