基于C#的開(kāi)源庫(kù)FluentFTP全面介紹
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
前言FluentFTP是提供給.NET和.NET Standard使用的,一個(gè)完全由托管的FTP和FTPS實(shí)現(xiàn)的經(jīng)過(guò)速度優(yōu)化的類庫(kù)。它提供了全面的FTP的指令,功能包括文件上傳/下載,SSL/TLS連接,自動(dòng)目錄清單列表解析,文件哈希/校驗(yàn)和,文件權(quán)限/CHMOD權(quán)限,F(xiàn)TP代理,UTF-8編碼支持,Async/await支持,Powershell支持等等。 FluentFTP完全是由C#語(yǔ)言編寫的,并且沒(méi)有額外的依賴。它是在寬松的MIT許可下發(fā)布的,因此,F(xiàn)luentFTP既可以用于私有的應(yīng)用程序,也可以用于自由/開(kāi)源的應(yīng)用程序。 如果你需要讓一個(gè)特定的問(wèn)題優(yōu)先進(jìn)行支持,可以考慮使用IssueHunt為處理這個(gè)問(wèn)題提供資金資助。 特性
發(fā)布穩(wěn)定的二進(jìn)制文件在NuGet上發(fā)布,包含在.NET/CLR應(yīng)用程序中使用FTP/FTPS所需的所有內(nèi)容。相關(guān)的用法,請(qǐng)參閱下面的示例用法的部分和文檔的部分。
FluentFTP工作在.NET和.NET Standard/.NET Core。
這些平臺(tái)也支持FluentFTP:(通過(guò).NET Standard)
所有平臺(tái)的二進(jìn)制文件都是由一個(gè)VS 2017項(xiàng)目來(lái)構(gòu)建的。您需要使用VS 2017來(lái)構(gòu)建或者修正FluentFTP。 使用例子//創(chuàng)建一個(gè)FTP客戶端 FtpClient client = new FtpClient(“123.123.123.123”);
//如果您沒(méi)有指定登錄的憑證,我們將使用“匿名”用戶賬戶 client.Credentials = new NetworkCredential(“david”,”pass123”);
//開(kāi)始連接到服務(wù)器 client.Connect();
//獲得一個(gè)在“/htdocs”目錄下的文件和文件夾的列表 foreach(FtpListItem item in client.GetListing(“/htdocs”)){ //如果這個(gè)是一個(gè)文件 if(item.Type == FtpFileSystemObjectType.File){ //獲得這個(gè)文件的大小 long size = client.GetFileSize(item.FullName); }
//獲得文件或者文件夾的修改日期和時(shí)間 DateTime time = client.GetModifiedTime(item.FullName);
//計(jì)算文件在服務(wù)器端的哈希值(默認(rèn)的算法) FtpHash hash = client.GetHash(item.FullName); }
//上傳一個(gè)文件 client.UploadFile(@”C:\MyVideo.mp4”,”/htdocs/MyVideo.mp4”);
//重命名這個(gè)上傳的文件 client.Rename(“/htdocs/MyVideo.mp4”,”/htdocs/MyVideo_2.mp4”);
//下載這個(gè)文件 client.DownloadFile(@”C:\MyVideo_2.mp4”,”/htdocs/MyVideo_2.mp4”);
//刪除文件 client.deleteFile(“/htdocs/MyVideo_2.mp4”);
//遞歸地刪除一個(gè)文件夾 client.deleteDirectory(“/htdocs/extras/”);
//檢查文件是不是存在 if(client.FileExists(“/htdocs/big2.txt”)){}
//檢查一個(gè)文件夾是不是存在 if(client.DirectoryExists(“/htdocs/extras/”)){}
//上傳一個(gè)文件,并且如果失敗,在失敗之前會(huì)重新嘗試三次 client.RetryAttempts=3;
client.UploadFile(@”C:\MyVideo.mp4”,”/htdocs/big.txt”,FtpExists.Overwrite,false,FtpVerify.Retry);
//斷開(kāi)連接!再見(jiàn)~ client.Disconnect(); Powershell你可以使用FluentFTP將文件從Powershell腳本傳輸?shù)紽TP服務(wù)器。開(kāi)始:
>. C:\scripts\FluentFTP.ps1 #Makes functions callable from PowerShell scripts
> Show-FtpFile -Site ftp.mysite.com -User bob -Password secure -FtpDirectory pub -FtpFileName "text*" > Rename-File -Site ftp.mysite.com -User bob -Password secure -FtpDirectory pub -oldName "Readme.txt -newName Readme.done" > Send-FtpFile -Site ftp.mysite.com -User bob -Password secure -FtpDirectory pub -fileName "Read*" > Get-FtpFile -Site ftp.mysite.com -User bob -Password secure -FtpDirectory pub -ftpfileName "Read*" > Remove-FtpFile -Site ftp.mysite.com -User bob -Password secure -FtpDirectory pub -ftpfileName "Read*" 在Powershell中運(yùn)行以下命令可以打印出每個(gè)命令的幫助: > get-help -full Show-FtpFile > get-help -full Rename-FtpFile > get-help -full Send-FtpFile > get-help -full Get-FtpFile > get-help -full Remove-FtpFile 文檔
常見(jiàn)問(wèn)題注:檢查這些常見(jiàn)問(wèn)題和已經(jīng)解決的常見(jiàn)問(wèn)題。 日志相關(guān)的常見(jiàn)問(wèn)題
連接相關(guān)的常見(jiàn)問(wèn)題
文件傳輸?shù)某R?jiàn)問(wèn)題
文件管理的常見(jiàn)問(wèn)題
Misc的常見(jiàn)問(wèn)題
一些非常常見(jiàn)的問(wèn)題
常見(jiàn)問(wèn)題
APIFtpClient類的全部的API文檔都是用來(lái)處理所有的FTP/FTPS功能。 注:所有的方法都支持同步和異步的版本。只需在.NET 4.5+的版本中,為Async/await語(yǔ)的添加“Async”后綴,或者在.NET 4.0及以下版本的方法中添加“Begin”/“End”的前綴。 連接
服務(wù)器
目錄清單
文件傳輸 高級(jí)API:
低級(jí)API:
文件管理 工作目錄(相對(duì)的路徑相對(duì)于當(dāng)前的工作目錄):
目錄:
文件:
文件權(quán)限 大多數(shù)的服務(wù)器支持的標(biāo)準(zhǔn)命令
只支持安裝并啟用了CHMOD擴(kuò)展的UNIX FTP服務(wù)器
文件哈希 (筆記:高級(jí)的文件傳輸API支持在上傳/下載之后自動(dòng)進(jìn)行文件哈希) 大多數(shù)的服務(wù)器支持的標(biāo)準(zhǔn)命令
僅由某些服務(wù)器支持的非標(biāo)準(zhǔn)的命令。查看更多
工具 請(qǐng)導(dǎo)入FluentFTP來(lái)使用這些擴(kuò)展方法,或者直接在FtpExtensions類中訪問(wèn)它們。
請(qǐng)直接訪問(wèn)FtpClient類下的這些靜態(tài)方法。
日志 有關(guān)日志和調(diào)試的幫助,請(qǐng)參閱FAQ的條目。
僅.NET Standard可用
僅.NET Framework可用
設(shè)置 FTP設(shè)置 可以自動(dòng)檢測(cè)服務(wù)器上的FTP連接設(shè)置。
主動(dòng)的FTP設(shè)置
FPTS設(shè)置 請(qǐng)?jiān)谡{(diào)用Connect()之前設(shè)置這些配置??梢?/em>自動(dòng)地檢測(cè)這些工作在你服務(wù)器上的FTPS連接設(shè)置。
文件清單列表設(shè)置
文件傳輸設(shè)置
超時(shí)設(shè)置
嵌套字(socket)設(shè)置
FTP支持映射表記錄了支持的FTP命令和相應(yīng)的API.. 連接指令
文件管理命令
文件哈希命令
常見(jiàn)問(wèn)題如何自動(dòng)檢測(cè)正確的鏈接設(shè)置?使用下面的代碼: FtpClient client = new FtpClient(hostname, username, password);//或者設(shè)置Host和Credentials var profiles = client.AutoDetect(); //如果找到任何配置文件,將代碼打印到控制臺(tái) if(profiles.Count > 0){ var code = profiles[0].ToCode(); Console.WriteLine(code); } 一旦你找一個(gè)工作連接配置文件后,使用生成的代碼快速連接到你的FTP服務(wù)器。 如何自動(dòng)連接到FTP或FTPS服務(wù)器?使用下面的代碼: FtpClient client = new FtpClient(hostname, username, password);//或者設(shè)置Host和Credentials client.AutoConnect(); 如何連接SSL/TLS?/如何使用FTPS?使用下面的代碼: FtpClient client = new FtpClient(hostname, username, password);//或者設(shè)置Host和Credentials client.EncryptionMode = FtpEncryptionMode.Explicit; client.SslProtocols = SslProtocols.Tls; client.ValidateCertificate += new FtpSslValidation(OnValidateCertificate); client.Connect(); void OnValidateCertificate(FtpClient control, FtpSslValidationEventArgs e){ //在這里添加邏輯以測(cè)試證書是否有效 e.Accept = true; } 如果你連接到服務(wù)器有任何的問(wèn)題,嘗試使用其中之一: 讓操作系統(tǒng)選擇最高和最相關(guān)的TLS協(xié)議。 client.SslProtocols = Security.Authentication.SslProtocols.None; 防止操作系統(tǒng)使用在.NET Framework中有問(wèn)題的TLS 1.0。 client.SslProtocols = SslProtocols.Default | SslProtocols.Tls11 | SslProtocols.Tls12; 如果你在Linux上使用并且使用SSL/TLS連接失敗,很可能是這個(gè)問(wèn)題。 如何在使用FTPS時(shí)驗(yàn)證服務(wù)器的證書?方法一:如果SSL證書沒(méi)有錯(cuò)誤則進(jìn)行連接。 cleint.ValidanteCertificate += new FtpSslValidation(delegate (FtpClient c, FtpSslValidtionEventArgs e){ if(e.PolicyErrors != System.Net.Security.SslPolicyErrors.None) { e.Accept = false; } else { e.Accept = true; } }); 方法二:如果證書與白名單證書匹配,則連接。 首先,您必須發(fā)現(xiàn)有效證書的字符串。使用此代碼將有效的證書字符串保存到文件中: cleint.ValidanteCertificate += new FtpSslValidation(delegate (FtpClient c, FtpSslValidtionEventArgs e){ File.WrtieAllText(@”c:\cert.txt”, e.Certificate.GetRawCertDataString()); }); 最后,使用這個(gè)代碼檢查收到的證書是否與您信任的證書匹配: string ValidCert = “<insert contents of cert.txt>”; cleint.ValidanteCertificate += new FtpSslValidation(delegate (FtpClient c, FtpSslValidtionEventArgs e){ if(e.PolicyErrors == SslPolicyErrors.None || e.Certificate.GetRawCertDataString() == ValidCert){ e.Accept = true; } else { Throw new Exception(“Invalid certificate : ” + e.PolicyErrors); } }); 如何使用SSL/TLS連接到Azure?假設(shè)您在Azure應(yīng)用程序服務(wù)實(shí)例上使用FTP發(fā)布服務(wù)。 如果您在連接Azure時(shí)遇到問(wèn)題,請(qǐng)確保您沒(méi)有“只使用FTPS”。根據(jù)Azure文檔,“僅支持FTPS”不支持TLS 1.0和1.1,這可能會(huì)在試圖將FluentFTP用于較舊版本的Windows時(shí)破壞連接。因此,當(dāng)您試圖連接到一個(gè)將會(huì)阻塞TLS 1.1的Azure FTP實(shí)例時(shí),連接將靜默地失敗,因?yàn)樗唤邮躎LS 1.2。 將設(shè)置更改為允許不安全的FTP之后,可以使用顯式和隱式SSL模式連接FTPS。 如何連接FTPS,然后切換回純文本(Plaintext)的FTP?當(dāng)你有一個(gè)FTP防火墻需要使用初文明的FTP的時(shí)候這是非常有用的。我們使用CCC命令指示服務(wù)器恢復(fù)到FTP。 在調(diào)用FtpClient類上的Connect()或任何其他方法之前設(shè)置此選項(xiàng)。 client.PlainTextEncryption = true; 如何連接SFTP?SFTP不被支持,因?yàn)樗荢SH下的FTP,一個(gè)完全不一樣的協(xié)議。請(qǐng)使用SSH.NET。 如何中使用匿名的FTP賬戶登錄?/我在登錄的時(shí)候遇到錯(cuò)誤但是我可以在Firefox/Filezilla中正常登錄不設(shè)置Credentials屬性,我們可以用匿名的身份登錄?;蛘吣梢允謩?dòng)指定以下內(nèi)容: client.Credentials = new NetworkCredential("anonymous", "anonymous"); 如何使用FTP代理登錄?創(chuàng)建一個(gè)FtpClientHttpProxy或者FtpClientUserAtHostProxy的對(duì)象實(shí)例,然后按照往常一樣使用FTP的屬性和方法。 如何追蹤文件的傳輸進(jìn)度?所有的高級(jí)的方法都提供了一個(gè)progress的參數(shù),被使用來(lái)跟蹤上傳或者下載的進(jìn)度。 在使用之前,先創(chuàng)建一個(gè)回調(diào)的方法來(lái)提供給上傳/下載的方法。它將隨著FtpProgress對(duì)象被調(diào)用,其中包含傳輸?shù)陌俜直群透鞣N統(tǒng)計(jì)數(shù)據(jù)。 如果你創(chuàng)建在你WinForm程序的UI中,可以創(chuàng)建一個(gè)Minimum = 0并且Maximum = 100的ProgressBar。 使用異步的API: //接受一個(gè)FtpProgress對(duì)象的回調(diào)方法 Progress<FtpProgress> progress = new Progress<FtpProgress>(x => { //當(dāng)進(jìn)度未知的時(shí)候,會(huì)收到-1 if(x.Progress < 0) { progressBar.IsIndeterminate = true; } else { progressBar.IsIndeterminate = false; progressBar.Value = x; } }); 使用同步的API: //接受一個(gè)FtpProgress對(duì)象的回調(diào)方法 Action<FtpProgress> progress = new Action<FtpProgress>(x => { //當(dāng)進(jìn)度未知的時(shí)候,會(huì)收到-1 if(x.Progress < 0) { progressBar.IsIndeterminate = true; } else { progressBar.IsIndeterminate = false; progressBar.Value = x; } }); 現(xiàn)在要調(diào)用上傳/下載方法并提供您剛才創(chuàng)建的新的progress對(duì)象。 使用異步的方式: await client.DownloadFileAsync(localPath, remotePath, FtpLocalExists.Overwrite, FluentFTP.FtpVerify.Retry, progress); 使用同步的方式: client.DownloadFile(localPath, remotePath, FtpLocalExists.Overwrite, FluentFTP.FtpVerify.Retry, progress); 對(duì)于.NET 2.0的用戶,通過(guò)IProgress類來(lái)實(shí)現(xiàn)。你傳遞的對(duì)象的Report()方法將會(huì)攜帶進(jìn)度的值被調(diào)用。 如何上傳動(dòng)態(tài)創(chuàng)建的數(shù)據(jù)?使用Upload()來(lái)上傳一個(gè)stream或者byte[]。 如何下載數(shù)據(jù)而不將其保存到磁盤?使用Download()將數(shù)據(jù)下載到一個(gè)stream或者byte[]中。 如何繼續(xù)下載一個(gè)文件?使用帶有existsMode設(shè)置為FtpLocalExists.Append的DownloadFile()或者DownloadFiles()。 //通過(guò)比較文件大小和本地文件的大小,只下載文件中缺少的部分 client.DownloadFile(@”C:\MyVideo.mp4”, “/htdocs/MyVideo.mp4”, FtpLocalExists.Append); 其他的配置:
如何繼續(xù)上傳一個(gè)文件?使用一個(gè)新的API UploadFile(): //通過(guò)比較文件大小和本地文件的大小,只上傳服務(wù)器文件中缺少的部分 client.UploadFile(@”C:\bigfile.iso”, “/htdocs/bigfile.iso”, FtpLocalExists.Append); 如何控制上傳和下載的速度?設(shè)置UploadRateLimit和DownloadRateLimit屬性來(lái)控制數(shù)據(jù)傳輸?shù)乃俣?。只?span style="margin: 0px; padding: 0px; color: rgb(51, 102, 255);">高級(jí)API才支持同步和異步版本,比如:
有關(guān)節(jié)流的最新改進(jìn),請(qǐng)參閱這篇文章。 如何驗(yàn)證文件的哈希值/校驗(yàn)和,如果校驗(yàn)和不匹配,如何重試?將FtpVerify選項(xiàng)設(shè)置添加到UploadFile()或DownloadFile()以啟用自動(dòng)校驗(yàn)和驗(yàn)證。 //上傳文件的時(shí)候重新嘗試設(shè)置為3次 client.RetryAttempts = 3; //上傳一個(gè)文件,在放棄之前或嘗試重傳3次 client.UploadFile(@"C:\MyVideo.mp4", "/htdocs/MyVideo.mp4", FtpExists.Overwrite, false, FtpVerify.Retry); 所有可能的配置:
如何追加到一個(gè)文件?使用API Upload(): //將數(shù)據(jù)追加到一個(gè)已經(jīng)存在的文件中 File.AppendAllText(@"C:\readme.txt", "text to be appended" + Environment.NewLine); //只有readme.txt的新部分將被寫入服務(wù)器 client.UploadFile("C:\readme.txt", "/htdocs/readme.txt", FtpExists.Append); 使用基于流的API OpenAppend(): using (FtpClient conn = new FtpClient()) { conn.Host = "localhost"; conn.Credentials = new NetworkCredential("ftptest", "ftptest"); using (Stream ostream = conn.OpenAppend("/full/or/relative/path/to/file")) { try { ostream.Position = ostream.Length; var sr = new StreamWriter(ostream); sr.WriteLine(...); } finally { ostream.Close(); conn.GetReply(); //從服務(wù)器讀取成功/失敗響應(yīng) } } } 如何使用低級(jí)的(low-level)API下載文件?使用API OpenRead(): //創(chuàng)建遠(yuǎn)程FTP流和本地文件流 using (var remoteFileStream = client.OpenRead(remotePath, FtpDataType.Binary)){ using (var newFileStream = File.create(localPath)){ //一次讀取8KB的數(shù)據(jù)(你可以增加數(shù)量) byte[] buffer = new byte[8 * 1024]; //下載文件到本地的流 int len; while ((len = remoteFileStream.Read(buffer, 0, buffer.Length)) > 0) { newFileStream.Write(buffer, 0, len); } } } //讀取FTP響應(yīng)并防止套接字上的過(guò)時(shí)數(shù)據(jù) client.GetReply(); 如果我的服務(wù)器不支持UTF-8,如何上傳/下載Unicode文件名的文件?手動(dòng)設(shè)置連接編碼,以確保特殊字符正常工作。 默認(rèn)你應(yīng)該使用的代碼頁(yè)(codepage)是1252 Windows Western。它支持英語(yǔ)+歐洲字符(重音字符)。 client.Encoding = System.Text.Encoding.GetEncoding(1252); //ANSI代碼頁(yè)1252(Windows Western) 以下是基于你需要的字符集的代碼頁(yè)的完整列表:
GetListing()如何在內(nèi)部工作?
如果這些都不能滿足你,你還可以退一步使用名稱清單列表(NLST命令),它比LIST和MLSD命令要慢很多。這是因?yàn)镹LST只發(fā)送文件名列表,沒(méi)有任何屬性。必須逐個(gè)文件地查詢服務(wù)器的文件大小、修改日期和類型(文件/文件夾)。通過(guò)FtpListOption.ForceNameList標(biāo)志,可以讓名稱清單列表可以被強(qiáng)制使用。 筆記:一些FTP服務(wù)器在列空文件夾的列表清單的時(shí)候不返回應(yīng)答,所以客戶端在另一端將沒(méi)有與服務(wù)器溝通的套接字。這些異常在內(nèi)部被捕獲,并返回一個(gè)空的文件列表。如果你需要檢查這個(gè)的捕獲的實(shí)現(xiàn),請(qǐng)?jiān)贔luentFTP項(xiàng)目中搜索FtpMissingSocketException的所有實(shí)例。 GetListing()如何返回一個(gè)遞歸的文件列表?在就版本的FluentFTP中,我們假定所有的服務(wù)器都支持通過(guò)List -R命令來(lái)遞歸列出文件的列表清單。然而,這導(dǎo)致了各種FTP服務(wù)器布置成遞歸列出清單的許多的問(wèn)題:GetListing()調(diào)用將簡(jiǎn)單地返回第一個(gè)目錄的內(nèi)容,而不包含任何子目錄。 因此,自從20.0.0版本,我們嘗試去檢查FTP服務(wù)器的軟件,并且如果我們確定它不支持遞歸列表,我們將自己動(dòng)手地進(jìn)行遞歸。我們開(kāi)始先假設(shè)所有服務(wù)器都不支持遞歸列表,然后將特定的服務(wù)器類型列入白名單。 如果您感覺(jué)GetListing()在使用遞歸列出列表清單的時(shí)候速度太慢,并且您知道您的FTP服務(wù)器支持LIST -R命令,然后請(qǐng)為您的服務(wù)器提供支持:
支持哪種散列命令?我們支持XCRC、XMD5和XSHA,它們是非標(biāo)準(zhǔn)命令,不包含任何形式的規(guī)范。它們不能保證工作,強(qiáng)烈建議您檢查FtpClient。在調(diào)用這些方法之前,為各自的標(biāo)志設(shè)置功能標(biāo)志(XCRC、XMD5、XSHA1、XSHA256、XSHA512)。 這里文章中描述的MD5命令支持也已經(jīng)被添加。在執(zhí)行命令之前,再次檢查FtpFeature.MD5。 對(duì)HASH命令的支持已經(jīng)添加到FluentFTP中。它支持從支持這個(gè)功能的服務(wù)器上檢索SHA-1、SHA-256、SHA-512和MD5散列。返回的FtpHash對(duì)象,它有一個(gè)具有針對(duì)給定流或本地文件檢查結(jié)果的方法。你可以在這個(gè)草案中了解更多關(guān)于HASH的信息。 如何在調(diào)試時(shí)追蹤FTP命令?在程序啟動(dòng)時(shí)執(zhí)行此操作(因?yàn)樗庆o態(tài)的,所以對(duì)所有FtpClient實(shí)例都有效)。 .NET Framework版本 FtpTrace.AddListener(new ConsoleTraceListener()); FtpTrace.LogUserName = false;//隱藏FTP用戶名 FtpTrace.LogPassword = false;//隱藏FTP密碼 FtpTrace.LogIP = false; //隱藏FTP的IP地址 .NET Standard版本 FtpTrace.LogToConsole = true; FtpTrace.LogUserName = false;//隱藏FTP用戶名 FtpTrace.LogPassword = false;//隱藏FTP密碼 FtpTrace.LogIP = false;//隱藏FTP的IP地址 如何在調(diào)試記錄所有的FTP命令到文件中?在程序啟動(dòng)時(shí)執(zhí)行此操作(因?yàn)樗庆o態(tài)的,所以對(duì)所有FtpClient實(shí)例都有效)。 .NET Framework版本 FtpTrace.AddListener(new TextWriterTraceListener("log_file.txt")); FtpTrace.LogUserName = false;//隱藏FTP用戶名 FtpTrace.LogPassword = false;//隱藏FTP密碼 FtpTrace.LogIP = false; //隱藏FTP的IP地址 .NET Standard版本 FtpTrace.LogToFile = “log_file.txt”; FtpTrace.LogUserName = false;//隱藏FTP用戶名 FtpTrace.LogPassword = false;//隱藏FTP密碼 FtpTrace.LogIP = false;//隱藏FTP的IP地址 如何將關(guān)鍵錯(cuò)誤記錄到文件中?這是生產(chǎn)服務(wù)器的推薦配置。僅在.NET Framework版本中被支持。 在程序啟動(dòng)時(shí)執(zhí)行此操作(因?yàn)樗庆o態(tài)的,所以對(duì)所有FtpClient實(shí)例都有效)。 FtpTrace.LogFunctions = false; FtpTrace.AddListener(new TextWriterTraceListener("log_file.txt"){ Filter = new EventTypeFilter(SourceLevels.Error) }); 如何禁用函數(shù)調(diào)用的日志記錄?在程序啟動(dòng)時(shí)執(zhí)行此操作(因?yàn)樗庆o態(tài)的,所以對(duì)所有FtpClient實(shí)例都有效)。 FtpTrace.LogFunctions = false; 如何中日志中省略掉敏感的信息?使用這些設(shè)置來(lái)控制日志中包含哪些數(shù)據(jù):
如何使用像NLog這樣的第三方日志記錄框架?FluentFTP有一個(gè)名為“FluentFTP”的內(nèi)置TraceSource,可用于調(diào)試和日志記錄。目前,除了.NET Standard之外,所有的.NET Framework版本都可以使用。通過(guò)寫入到程序或者配置到你的app.config或者web.config都可以將實(shí)現(xiàn)任何的TraceListener附加到類庫(kù)程序中。這將允許直接日志記錄或轉(zhuǎn)發(fā)到第三方日志記錄框架。 大多數(shù)跟蹤消息的類型為Verbose或Information,通常可以忽略,除非進(jìn)行調(diào)試。大多數(shù)被忽略的異常被歸類為Warning,但是返回布爾值表示成功/失敗的方法,將以Error級(jí)別記錄失敗原因。如果您使用的是.NET Standard,并且設(shè)置了DEDUG標(biāo)志,然后所有日志消息將通過(guò)Debug.Write(message)方式發(fā)出。 在代碼中附加TraceListener: TraceListener console = ConsoleTraceListener() { Filter = new EventTypeFilter(SourceLevels.Verbose | SourceLevels.ActivityTracking) }; FtpTrace.AddListener(console); 通過(guò)配置文件附加: <system.diagnostics> <trace autoflush="true"></trace> <sources> <source name="FluentFTP"> <listeners> <clear /> <!--附加一個(gè)Console控制臺(tái)監(jiān)聽(tīng)器--> <add name="console" /> <!--附加一個(gè)File監(jiān)聽(tīng)器--> <add name="file" /> <!--附加一個(gè)用戶自定義的監(jiān)聽(tīng)器--> <add name="myLogger" /> <!--附加一個(gè)NLog監(jiān)聽(tīng)器--> <add name="nlog" /> </listeners> </source> </sources> <sharedListeners> <!--定義一個(gè)Console控制臺(tái)監(jiān)聽(tīng)器--> <add name="console" type="System.Diagnostics.ConsoleTraceListener" /> <!--定義一個(gè)File監(jiān)聽(tīng)器 --> <add name="file" type="System.Diagnostics.TextWriterTraceListener" initializeData="outputFile.log"> <!--只寫入錯(cuò)誤--> <filter type="System.Diagnostics.EventTypeFilter" initializeData="Error" /> </add> <!--定義一個(gè)用戶自定義的監(jiān)聽(tīng)器--> <add name="custom" type="MyNamespace.MyCustomTraceListener /> <!--附加一個(gè)NLog監(jiān)聽(tīng)器--> <add name="nlog" type="NLog.NLogTraceListener, NLog" /> </sharedListeners> </system.diagnostics> EnableThreadSafeDataConnections做什么?EnableThreadSafeDataConnections是由最初的作者構(gòu)建的一個(gè)較老的特性。如果為true,那么每當(dāng)您試圖上傳/下載文件時(shí),它都會(huì)打開(kāi)一個(gè)新的FTP客戶端實(shí)例(并重新連接到服務(wù)器)。它曾經(jīng)是默認(rèn)設(shè)置,但它嚴(yán)重影響了性能,所以我禁用了它,發(fā)現(xiàn)許多問(wèn)題都得到了解決,性能也得到了恢復(fù)。我相信如果開(kāi)發(fā)者想要多線程上傳,他們應(yīng)該啟動(dòng)一個(gè)新的BackgroundWorker并在該線程中創(chuàng)建/使用FtpClient。如果你想要并發(fā)上傳,可以嘗試一下。 如何對(duì)FluentFTP做一些修改?/如何提交一個(gè)拉取請(qǐng)求(a pull reqest)?首先你必須“fork”FluentFTP,然后對(duì)本地版本進(jìn)行更改,當(dāng)提交“pull request”請(qǐng)求讓我合并你的變化。
如何檢測(cè)正在連接的服務(wù)器的類型?您可以讀取ServerType來(lái)獲得您所連接的FTP服務(wù)器軟件的確切類型。我們動(dòng)態(tài)根據(jù)我們接連到服務(wù)器時(shí)服務(wù)器所發(fā)送的歡迎信息(the welcome message),來(lái)檢測(cè)FTP服務(wù)器軟件。我們目前可以檢測(cè)如下軟件類型:
您還可以讀取ServerOS來(lái)獲得所連接的FTP服務(wù)器的操作系統(tǒng)。我們可以檢測(cè)如下系統(tǒng)到:
如何使用客戶端證書登入FTPS?添加你的證書到ClientCertificates,然后再調(diào)用Connect()。 client.EncryptionMode = FtpEncryptionMode.Explicit; client.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12; client.SocketKeepAlive = false; client.ClientCertificates.Add(new X509Certificate2("C:\mycert.cer")); client.ValidateCertificate += (control, e) => { e.Accept = e.PolicyErrors == SslPolicyErrors.None; }; client.Connect(); 并確保:
如何從一個(gè)文件捆綁X509證書?您需要將證書添加到本地存儲(chǔ)(local store),然后執(zhí)行以下操作: FluentFTP.FtpClient client = new FluentFTP.FtpClient("WWW.MYSITE.COM", "USER","PASS"); //選擇證書并將它添加到客戶端 X509Store store = new X509Store("MY", StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates; X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false); X509Certificate2Collection scollection = X509Certificate2UI.selectfromCollection(fcollection, "select a certificate", "select a certificate", X509selectionFlag.Multiselection); if (scollection.Count != 1) { throw new Exception("Error: You have not chosen exactly one certificate"); } foreach (X509Certificate2 x509 in scollection) { client.ClientCertificates.Add(x509); } store.Close(); //client.ReadTimeout = 10000; client.Connect(); 這是另外一種方式。使用X509Certificate2。我一直無(wú)法讓X509Certificate證書工作,從我的查閱的資料來(lái)看,這是因?yàn)樗且粋€(gè)不完整的實(shí)現(xiàn)。 public void InitSFTP() { FluentFTP.FtpClient client = new FluentFTP.FtpClient("WWW.MYSITE.COM", "USER", "PASS"); X509Certificate2 cert_grt = new X509Certificate2("C:\mycert.xyz"); client.EncryptionMode = FtpEncryptionMode.Explicit; client.DataConnectionType = FtpDataConnectionType.PASV; client.DataConnectionEncryption = true; client.ClientCertificates.Add(cert_grt); client.ValidateCertificate += new FtpSslValidation(OnValidateCertificate); client.Connect(); } private void OnValidateCertificate(FtpClient control, FtpSslValidationEventArgs e) { e.Accept = true; } 解決問(wèn)題在Visual Studio 2010中Fluent安裝失?。骸癝ystem.Runtime”已經(jīng)為“FluentFTP”定義了一個(gè)依賴項(xiàng)你的VS使用了一個(gè)老版本的nuget.exe,所以它不能正確安裝最新的FluentFTP。你必須下載nuget.exe 并手動(dòng)執(zhí)行下面這些命令: cd D:\Projects\MyProjectDir C:\Nuget\nuget.exe install FluentFTP 上傳一個(gè)帶有特殊字符的文件,像是“Caffè.png”,在FTP服務(wù)器上,它表現(xiàn)為“Caff?.png”。這個(gè)服務(wù)器只支持ASCII,但是這個(gè)“è”是ASCII。FileZilla可以上傳這個(gè)文件,并且沒(méi)有任何問(wèn)題手動(dòng)設(shè)置連接編碼,以確保特殊字符正常工作。 默認(rèn)你應(yīng)該使用的代碼頁(yè)(codepage)是1252 Windows Western。它支持英語(yǔ)+歐洲字符(重音字符)。 client.Encoding = System.Text.Encoding.GetEncoding(1252); //ANSI代碼頁(yè)1252(Windows Western) 如何文件名中含有俄文字母,我無(wú)法刪除這個(gè)文件。但是FileZilla可以刪除這個(gè)文件,并且沒(méi)有問(wèn)題手動(dòng)設(shè)置連接編碼,以確保特殊字符正常工作。 對(duì)于俄語(yǔ),你需要使用代碼頁(yè)1251 Windows Cyrillic client.Encoding = System.Text.Encoding.GetEncoding(1251); //ANSI代碼頁(yè)1251(Windows Cyrillic) 我總是在我的Azure WebApp中發(fā)生TimeoutException異常首先嘗試減少Azure需要的套接字輪詢間隔。 client.SocketPollInterval = 1000; 如果這也不管用,那么試著減少超時(shí)時(shí)間。 client.SocketPollInterval = 1000; client.ConnectTimeout = 2000; client.ReadTimeout = 2000; client.DataConnectionConnectTimeout = 2000; client.DataConnectionReadTimeout = 2000; 如果這些都不起作用,請(qǐng)記住Azure有一個(gè)間歇性的bug,在這個(gè)bug中,它會(huì)在FTP請(qǐng)求期間更改ip地址。連接是使用IP地址A建立的,Azure使用IP地址B進(jìn)行數(shù)據(jù)傳輸,這在很多防火墻上是不允許的。這是一個(gè)已知的Azure bug。 許多的命令無(wú)法在Windows CE上正常工作根據(jù)MSDN上所說(shuō)的,Windows CE上的FTP實(shí)現(xiàn)是最少的,并通過(guò)源代碼開(kāi)放定制。許多高級(jí)命令如CHMOD都不受支持。 使用OpenWrite/OpenAppend成功傳輸單個(gè)文件后,后續(xù)文件失敗,出現(xiàn)一些隨機(jī)錯(cuò)誤,如“格式錯(cuò)誤的PASV響應(yīng)”您需要在傳輸完文件之后調(diào)用FtpReply status = GetReply(),以確保沒(méi)有遺留過(guò)時(shí)的數(shù)據(jù),以免打亂后續(xù)命令。 在FTPS的登入期間,SSL協(xié)商非常緩慢FluentFTP在.NET Framework的底層使用SslStream。SslStream使用一個(gè)windows的特性功能來(lái)動(dòng)態(tài)地更新Root CA證書,這可能會(huì)導(dǎo)致證書認(rèn)證過(guò)程中的長(zhǎng)時(shí)間延遲。這可能會(huì)在FluentFTP中引起與SocketPollInterval屬性相關(guān)的問(wèn)題,該屬性用于檢查客戶機(jī)和服務(wù)器之間的不合理斷開(kāi)連接。這個(gè)MSDN博客討論了SslStream的問(wèn)題,并討論了如何禁用Root CA證書的自動(dòng)更新。 FluentFTP記錄認(rèn)證所需的時(shí)間。如果您認(rèn)為自己正遭受這個(gè)問(wèn)題的困擾,那么請(qǐng)查看Examples\ debug .cs以獲取有關(guān)檢索調(diào)試信息的信息。 無(wú)法從傳輸連接讀取數(shù)據(jù):遠(yuǎn)程主機(jī)強(qiáng)制關(guān)閉了現(xiàn)有連接這意味著服務(wù)器上的 [FTP守護(hù)進(jìn)程(FTP daemon)] 服務(wù)沒(méi)有運(yùn)行(可能不是這種情況),或者服務(wù)當(dāng)前仍然忙于執(zhí)行另一個(gè)操作。這聽(tīng)起來(lái)就像服務(wù)器返回一條消息,表明它仍然在執(zhí)行上一個(gè)操作。 嘗試減少輪詢間隔以確保連接不會(huì)超時(shí)。 client.SocketPollInterval = 1000; 該文章在 2023/10/9 9:50:00 編輯過(guò) |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |