C# FTP調(diào)用的實(shí)現(xiàn)示例
1. 使用 .NET 自帶 FtpWebRequest 實(shí)現(xiàn) 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($"上傳狀態(tài): {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($"刪除狀態(tài): {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($"刪除目錄狀態(tài): {response.StatusDescription}");
}
}2. 進(jìn)階:斷點(diǎn)續(xù)傳(部分實(shí)現(xiàn))
.NET標(biāo)準(zhǔn)庫不直接支持FTP斷點(diǎn)續(xù)傳,但可以通過設(shè)置 ContentOffset 實(shí)現(xiàn)下載斷點(diǎn)續(xù)傳:
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響應(yīng): {ftpResponse.StatusDescription}");
}
else
{
Console.WriteLine($"網(wǎng)絡(luò)異常: {ex.Message}");
}
}
catch (Exception ex)
{
Console.WriteLine($"其他異常: {ex.Message}");
}4. 推薦:使用 FluentFTP 第三方庫(更強(qiáng)大)
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 支持?jǐn)帱c(diǎn)續(xù)傳、批量操作、進(jìn)度回調(diào)、SFTP等,API更現(xiàn)代,推薦生產(chǎn)環(huán)境使用。
5. 常見問題與建議
- 推薦使用被動(dòng)模式,防火墻友好:
request.UsePassive = true; - FTP明文傳輸不安全,敏感業(yè)務(wù)建議用 SFTP/FTPS
- 及時(shí)關(guān)閉連接和流,防止資源泄漏
- 大文件建議分塊/斷點(diǎn)續(xù)傳,提升健壯性
- 批量操作建議用多線程或異步(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. 進(jìn)度條與回調(diào)監(jiān)聽
FluentFTP 支持進(jìn)度回調(diào),非常適合大文件或批量傳輸場(chǎng)景。
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,可結(jié)合 async/await 實(shí)現(xiàn)高并發(fā):
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,結(jié)合異步API。
9. SFTP 實(shí)現(xiàn)(推薦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. 斷點(diǎn)續(xù)傳(FluentFTP示例)
client.UploadFile(localFile, remoteFile, FtpExists.Resume, false, FtpVerify.Retry); client.DownloadFile(localFile, remoteFile, FtpLocalExists.Resume, FtpVerify.Retry);
Resume模式會(huì)自動(dòng)檢測(cè)已上傳/下載的字節(jié)數(shù),斷點(diǎn)續(xù)傳。
13. 連接池設(shè)計(jì)建議
- 對(duì)于高并發(fā)場(chǎng)景,建議用對(duì)象池(如自定義或結(jié)合 Microsoft.Extensions.ObjectPool)。
- 每個(gè)線程/任務(wù)從池中借出連接,用完歸還,避免頻繁連接/斷開。
- FluentFTP和SSH.NET都可自定義連接池(實(shí)現(xiàn) IDisposable,支持多線程)。
14. 跨平臺(tái)兼容性
- .NET Core/6/7 支持 FluentFTP、SSH.NET,可在 Windows/Linux/Mac 部署。
- 文件路徑注意區(qū)分
/與\,建議用Path.Combine。 - 字符編碼建議統(tǒng)一 UTF-8,避免中文亂碼。
15. 日志與監(jiān)控
- FluentFTP支持事件監(jiān)聽,可記錄每次上傳/下載/異常。
- 企業(yè)應(yīng)用建議集成 Serilog/NLog/Log4Net 實(shí)現(xiàn)日志持久化與告警。
- 可結(jié)合 Prometheus/Grafana 采集傳輸量、錯(cuò)誤率等指標(biāo)。
16. 安全加固建議
- FTP傳輸建議啟用 FTPS(SSL/TLS),或優(yōu)先用 SFTP。
- 密碼、主機(jī)等敏感信息用配置中心或環(huán)境變量管理,不要硬編碼。
- 限制服務(wù)器端口、白名單IP,避免暴露在公網(wǎng)。
- 定期更換賬號(hào)密碼,開啟服務(wù)器日志審計(jì)。
17. 企業(yè)應(yīng)用架構(gòu)建議
- 封裝 FTP/SFTP 工具類或服務(wù),業(yè)務(wù)代碼只調(diào)用接口。
- 支持批量任務(wù)、斷點(diǎn)續(xù)傳、自動(dòng)重試、進(jìn)度回調(diào)。
- 結(jié)合定時(shí)任務(wù)/消息隊(duì)列,實(shí)現(xiàn)大文件/多文件異步傳輸。
- 日志與監(jiān)控全鏈路覆蓋,保證可運(yùn)維、可追溯。
18. 面試進(jìn)階問題&答題思路
如何實(shí)現(xiàn)高可用的 FTP/SFTP 文件服務(wù)?
- 多節(jié)點(diǎn)部署,連接池管理,自動(dòng)重試,斷點(diǎn)續(xù)傳,監(jiān)控告警。
FTP/SFTP在分布式系統(tǒng)中的應(yīng)用場(chǎng)景?
- 跨系統(tǒng)文件同步、定時(shí)批量數(shù)據(jù)交換、異地備份、與微服務(wù)/大數(shù)據(jù)平臺(tái)集成等。
如何應(yīng)對(duì)大文件傳輸中的網(wǎng)絡(luò)抖動(dòng)和中斷?
- 斷點(diǎn)續(xù)傳、自動(dòng)重連、分塊傳輸、錯(cuò)誤重試、傳輸進(jìn)度保存。
如何保證FTP/SFTP服務(wù)的安全性和合規(guī)性?
- 使用加密協(xié)議(FTPS/SFTP)、權(quán)限細(xì)分、日志審計(jì)、配置白名單。
C# FTP/SFTP與Java實(shí)現(xiàn)有何異同?
- API不同,原理一致;C#推薦FluentFTP/SSH.NET,Java推薦Commons Net/JSch。
到此這篇關(guān)于C# FTP調(diào)用的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)C# FTP調(diào)用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#?winform跨線程操作控件的實(shí)現(xiàn)
本文主要介紹了C#?winform跨線程操作控件的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06
C#條件拼接Expression<Func<T, bool>>的使用
本文主要介紹了C#條件拼接Expression<Func<T, bool>>的使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
使用C#和Jieba.NET實(shí)現(xiàn)中英文混合文本關(guān)鍵詞的提取功能
Jieba.NET?是一個(gè)在?C#?中實(shí)現(xiàn)的分詞庫,它基于?Java?的?jieba?分詞庫,并進(jìn)行了?C#?語言的移植,Jieba?是一個(gè)高效的中文分詞工具,能夠處理全模式、精確模式以及搜索引擎模式,本文給大家介紹了如何使用C#和Jieba.NET實(shí)現(xiàn)中英文混合文本關(guān)鍵詞的提取功能2025-03-03
C#如何優(yōu)雅的對(duì)WinForm窗體應(yīng)用程序進(jìn)行權(quán)限控制
經(jīng)常會(huì)出現(xiàn)winfrom頁面需要加載權(quán)限樹,下面這篇文章主要給大家介紹了關(guān)于C#如何優(yōu)雅的對(duì)WinForm窗體應(yīng)用程序進(jìn)行權(quán)限控制的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-11-11
C#中Hashtable與Dictionary的用法對(duì)比及選擇
這篇文章主要介紹了C#中Hashtable與Dictionary的用法對(duì)比及選擇方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03

