C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C# FTP调用

C# FTP调用的实现示例

作者:猩火燎猿

本文介绍了.NET平台实现FTP/SFTP操作的多种方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

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. 常见问题与建议

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. 连接池设计建议

14. 跨平台兼容性

15. 日志与监控

16. 安全加固建议

17. 企业应用架构建议

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。

到此这篇关于C# FTP调用的实现示例的文章就介绍到这了,更多相关C# FTP调用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文