FluentFTP中文翻译
翻译时间:2020/1/28
谢谢支持与关注!~
请勿转载或者以任何形式的进行抄写!~
本文由博主自译,其中有部分内容属于博主个人理解,如果有错误请多多包涵!
原文的地址:https://github.com/robinrodricks/FluentFTP
翻译 by恋如雨止
博客园:https://www.cnblogs.com/Jeffrey-Chou/
如果想要Word版本的翻译文档请评论留下QQ注明要翻译文档,看到我都会给的!~
前言
FluentFTP是提供给.NET和.NET Standard使用的,一个完全由托管的FTP和FTPS实现的经过速度优化的类库。它提供了全面的FTP的指令,功能包括文件上传/下载,SSL/TLS连接,自动目录清单列表解析,文件哈希/校验和,文件权限/CHMOD权限,FTP代理,UTF-8编码支持,Async/await支持,Powershell支持等等。
FluentFTP完全是由C#语言编写的,并且没有额外的依赖。它是在宽松的MIT许可下发布的,因此,FluentFTP既可以用于私有的应用程序,也可以用于自由/开源的应用程序。
如果你需要让一个特定的问题优先进行支持,可以考虑使用IssueHunt为处理这个问题提供资金资助。
特性
- 全面支撑FTP、FTPS(SSL下的FTP)、客户端证书FTP和CCC(用于FTP防火墙)的FTPS
- 文件管理:
- 为主要的服务器类型(例如Unix、Windows/IIS、Azure、Pure-FTPd、ProFTPD、Vax、VMS、OpenVMS、Tandem、HP NonStop Guardian、IBM OS/400、AS400、Windows CE、Serv-U)提供文件和文件夹清单列表显示
- 完全递归的目录清单列表和目录删除(手动递归和服务器递归)
- 带有进度跟踪方式,轻松地从服务器上上传和下载一个文件
- 自动验证文件的哈希值,并且在文件哈希值不匹配的时候重新尝试传输
- 多文件传输的可配置错误处理(忽略/终止/抛出)
- 使用标准的流,轻松地从服务器读取和写入文件数据
- 创建、附加、读取、写入、重命名、移动删除文件和文件夹
- 递归删除文件夹及其所有内容
- 获取文件/文件夹信息(存在、大小、安全标志、修改日期/时间)
- 获取和设置文件的权限(所有者、组、其他)
- 绝对路径或相对路径(相对于“工作目录”)
- 获取文件的哈希值和校验和(SHA-1、SHA-256、SHA-512和MD5)
- 取消对符号链接的引用,以计算链接的文件/文件夹
- 通过可配置的速度限制,节流上传和下载
- FTP协议:
- 自动检测工作连接设置和自动连接协定
- 自动检测FTP服务器软件以及它的性能
- 对FTP命令的广泛的支持,包括一些特定于服务器的命令
- 使用Execute()方法可以轻松地发送服务器特定的FTP命令
- 使用.NET的SslStream,显式或者隐式对控制和数据提供SSL连接的支持
- 无源和有源的数据连接(PASV、EPSV、PORT和EPRT)
- 支持Unix CHMOD,PRET,ProFTPD的SITE MKDIR和RMDIR命令,Serv-U的RMDA命令
- 支持FTP代理(User@Host,HTTP 1.1,BlueCoat)
- FTP命令日志通过使用TraceListeners(密码省略)来跟踪或者记录输出到一个文件中
- 不支持SFTP,因为它是通过SSH的FTP,这是一个完全不同的协议(请使用SSH.NET来处理)
- 异步支持:
- 对于所有的方法可以通过使用async/await来实现同步和异步的方法
- 通过使用IAsyncResult方式(Begin*/End*)支持.NET 4.0及其以下的的版本,来实现方法的异步调用
- 所有的异步方法都可以通过传递一个CancellationToken来实现中途的取消
- 所有的异步方法都遵循ReadTimeout,并且在超时的时候,它们会自动取消自己
- 通过克隆文件传输的FTP控制连接来提高文件线程的安全性(可选)
- 实现自己内部的锁定,以保持事务的同步
- 可扩展:
- 轻松地添加对更多的代理类型的支持(简单地继承FTPClientProxy)
- 轻松地取消对目录清单列表解析器的支持(参阅例子CustomParser)
- 通过使用FtpTrace.AddListener来实现轻松的添加自定义日志/跟踪的功能
- 通过扩展FluentFTP.ps1中的脚本,可以轻松的添加自己的Powershell命令
发布
稳定的二进制文件在NuGet上发布,包含在.NET/CLR应用程序中使用FTP/FTPS所需的所有内容。相关的用法,请参阅下面的示例用法的部分和文档的部分。
- Nuget(最新的)
- Release Notes(每个发布版本的特性和修复)
FluentFTP工作在.NET和.NET Standard/.NET Core。
平台 |
二进制文件夹 |
.NET 2.0 |
net20 |
.NET 3.5 |
net35 |
.NET 4.0 |
net40 |
.NET 4.5 |
net45 |
.NET Standard 1.4 |
netstandard1.4 |
.NET Standard 1.6 |
netstandard1.6 |
.NET Standard 2.0 |
Netstandard2.0 |
这些平台也支持FluentFTP:(通过.NET Standard)
- Mono 4.6
- Xamarin.iOS 10.0
- Xamarin.Android 10.0
- Universal Windows Platform 10.0
所有平台的二进制文件都是由一个VS 2017项目来构建的。您需要使用VS 2017来构建或者修正FluentFTP。
使用例子
//创建一个FTP客户端 FtpClient client = new FtpClient(“123.123.123.123”); //如果您没有指定登录的凭证,我们将使用“匿名”用户账户 client.Credentials = new NetworkCredential(“david”,”pass123”); //开始连接到服务器 client.Connect(); //获得一个在“/htdocs”目录下的文件和文件夹的列表 foreach(FtpListItem item in client.GetListing(“/htdocs”)){ //如果这个是一个文件 if(item.Type == FtpFileSystemObjectType.File){ //获得这个文件的大小 long size = client.GetFileSize(item.FullName); } //获得文件或者文件夹的修改日期和时间 DateTime time = client.GetModifiedTime(item.FullName); //计算文件在服务器端的哈希值(默认的算法) FtpHash hash = client.GetHash(item.FullName); } //上传一个文件 client.UploadFile(@”C:\MyVideo.mp4”,”/htdocs/MyVideo.mp4”); //重命名这个上传的文件 client.Rename(“/htdocs/MyVideo.mp4”,”/htdocs/MyVideo_2.mp4”); //下载这个文件 client.DownloadFile(@”C:\MyVideo_2.mp4”,”/htdocs/MyVideo_2.mp4”); //删除文件 client.DeleteFile(“/htdocs/MyVideo_2.mp4”); //递归地删除一个文件夹 client.DeleteDirectory(“/htdocs/extras/”); //检查文件是不是存在 if(client.FileExists(“/htdocs/big2.txt”)){} //检查一个文件夹是不是存在 if(client.DirectoryExists(“/htdocs/extras/”)){} //上传一个文件,并且如果失败,在失败之前会重新尝试三次 client.RetryAttempts=3; client.UploadFile(@”C:\MyVideo.mp4”,”/htdocs/big.txt”,FtpExists.Overwrite,false,FtpVerify.Retry); //断开连接!再见~ client.Disconnect();
Powershell
你可以使用FluentFTP将文件从Powershell脚本传输到FTP服务器。开始:
- 在Powershell中,按照它的报告下载所有的文件
- 将内容放入C:\Scripts或您选择的任何的文件夹中
- 在Powershell中运行这个命令,使FluentFTP函数可用:
>. 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中运行以下命令可以打印出每个命令的帮助:
> 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
文档
- API 文档
- 连接(Connection)
- 服务器(Server)
- 文件夹清单列表(Directory Listing)
- 文件传输(File Transfer)
- 文件管理(File Management)
- 文件权限(FIle Permissions)
- 文件哈希(File Hashing)
- 工具(Utilities)
- 日志(Logging)
- 设置
- FTP设置(FTP Settings)
- 显式的FTP设置(Active FTP Settings)
- FTPS设置(FTPS Setting)
- 文件列表化设置(File Listing Settings)
- 文件传输设置(File Transfer Settings)
- 超时设置(Timeout Settings)
- Socket连接设置(Socket Settings)
- FTP支持表
- 例子
- 发布日志
- 相关注释
常见问题
注:检查这些常见问题和已经解决的常见问题。
日志相关的常见问题
- 如何在调试时追踪FTP命令?
- 如何在调试记录所有的FTP命令?
- 如何将关键错误记录到文件中?
- 如何禁用函数调用的日志记录?
- 如何中日志中省略掉敏感的信息?
- 如何使用像NLog这样的第三方日志记录框架?
连接相关的常见问题
- 如何自动检测正确的连接设置?
- 如何自动连接到FTP或FTPS服务器?
- 如何连接SSL/TLS?如何使用FTPS?
- 如何在使用FTPS时验证服务器的证书?
- 如何使用SSL/TLS连接到Azure?
- 如何连接FTPS,然后切换回纯文本(Plaintext)的FTP?
- 如何连接SFTP?
- 如何中使用匿名的FTP账户登录?
- 如何使用FTP代理登录?
- 如何检测正在连接的服务器的类型?
- 如何使用客户端证书登入FTPS?
- 如何从一个文件捆绑X509证书?
文件传输的常见问题
- 如何追踪文件的传输进度?
- 如何上传动态创建的数据?
- 如何下载数据而不将其保存到磁盘?
- 如何继续下载一个文件?
- 如何继续上传一个文件?
- 如何控制上传和下载的速度?
- 如何验证文件的哈希值/校验和,如果校验和不匹配,如何重试?
- 如何追加到一个文件?
- 如何使用低级的(low-level)API下载文件?
- 如果我的服务器不支持UTF-8,如何上传/下载Unicode文件名的文件?
文件管理的常见问题
- GetListing()如何在内部工作?
- GetListing()如何返回一个递归的文件列表?
- 支持哪种散列命令?
Misc的常见问题
- EnableThreadSafeDataConnections做什么?
- 如何对FluentFTP做一些修改?
- 如何提交一个拉取请求(a pull reqest)?
一些非常常见的问题
- 无法从传输连接读取数据:远程主机强制关闭了现有连接
- 尝试从套接字流(the socket stream)读取数据时超时
- FTPS不能在Linux上工作,因为它不支持SSL会话恢复
常见问题
- 我在登陆时发生错误,但是我可以在Firefox/Filezilla中正常登陆
- 在Visual Studio 2010中Fluent安装失败:“System.Runtime”已经为“FluentFTP”定义了一个依赖项
- 上传一个带有特殊字符的文件,像是“Caffè.png”,在FTP服务器上,它表现为“Caff?.png”。这个服务器只支持ASCII,但是这个“è”是ASCII。FileZilla可以上传这个文件,并且没有任何问题
- 如何文件名中含有俄文字母,我无法删除这个文件。但是FileZilla可以删除这个文件,并且没有问题
- 我总是在我的Azure WebApp中发生TimeoutException异常
- 许多的命令无法在Windows CE上正常工作
- 使用OpenWrite/OpenAppend成功传输单个文件后,后续文件失败,出现一些随机错误,如“格式错误的PASV响应”
- 在FTPS的登入期间,SSL协商非常缓慢
API
FtpClient类的全部的API文档都是用来处理所有的FTP/FTPS功能。
注:所有的方法都支持同步和异步的版本。只需在.NET 4.5+的版本中,为Async/await语的添加“Async”后缀,或者在.NET 4.0及以下版本的方法中添加“Begin”/“End”的前缀。
连接
- new FtpClient() - 创建并返回一个新的FTP客户端实例。
- Host - FTP服务器的IP地址或者是主机名称。是必须的。
- Port - FTP连接的端口。默认为:自动(依据FTPS的配置config为21或者是990端口)
- Credentials - FTP的所使用的用户名称和密码。必须是在服务器上注册的有效的用户账户。默认为:anonymous/anonymous
- Connect() - 连接到FTP服务器(如果配置了的情况下会使用TLS/SSL)。
- Disconnect() - 立即关闭与服务器的FTP连接。
- AutoDetect() - 自动发现FTP连接的设置并且返回这些连接的配置文件。
- AutoConnect() - 自动发现FTP连接的设置并且使用这些配置去连接服务器。
- Excute() - 执行自定义或不支持的命令。
- IsConnected - 检查连是否仍然是活动的。
- IsClose - 检查此控制连接是否为克隆。默认为:false
- LastReply - 返回从服务器接收到的最后一个FtpReply。
服务器
- ServerType - 获得我们所连接的FTP服务器软件的类型,返回值为FtpServer枚举类型。请参阅受支持的FTP服务器列表。默认值为:FtpServer.Unknown
- ServerOS - 获得我们所连接的FTP服务器的操作系统的软件类型,返回值为FtpOS枚举类型。请参阅支持的操作系统的类型列表。默认值为:FtpOS.Unknown
- SystemType - 获取我们所连接的系统/服务器的类型。
- Capabilities - 获取服务器的性能(由标志位标识)。
- HasFeature() - 检查服务器是不是支持某个特定的特性(FtpCapability)。
目录清单
- GetListing() - 获得一个给定的文件夹的目录清单。添加FtpListOption.Recursive来递归地列出所有子目录的目录清单。每一个文件或者文件夹返回一个带有所有可用属性集合的FtpListItem。每一个FtpListItem包含:
- Type:对象的类型(文件、目录或链接)。
- Name:对象的名称(去除路径)。
- FullName:对象的完整文件路径。如果文件名看上去是错误的,那么请选择正确的编码。
- Created:对象的创建日期/时间。如果服务器没有提供这个值,默认值为:DateTime.MinValue。
- Modified:对象的最近一次的修改日期/时间。如果您获得了一个不正确的值,那么尝试添加FtpListOption.Modify标志位来使用另外一种MDTM命令的方式加载对象的修改时间。如果服务器没有提供这个值,默认值为:DateTime.MinValue
- Size:文件的字节大小。如果您获得了一个不正确的值,那么尝试添加FtpListOption.Size标志位来使用另外一种SIZE命令的方式加载文件的大小。如果服务器没有提供这个值,默认值为:0。
- LinkTarget:连接指向的完整文件路径。仅为符号连接填充。
- LinkObject:连接指向的文件/文件夹。在FtpListOption.DerefLink标志位被使用的时候,仅用于符号连接填充。
- SpecialPermissions:获得特殊的权限,比如Stiky、SUID和SGID。
- Chmod:对象的CHMOD权限。例如644或者755。如果服务器没有提供这个值,默认值为:0。
- OwnerPermissions:用户的权限。“r”、“w”、“x”的任意组合(使用FtpPermission枚举)。如果服务器没有提供这个值,默认值为:FtpPermission.None。
- GroupPermissions:组的权限。“r”、“w”、“x”的任意组合(使用FtpPermission枚举)。如果服务器没有提供这个值,默认值为:FtpPermission.None。
- OtherPermissions:其他权限。“r”、“w”、“x”的任意组合(使用FtpPermission枚举)。如果服务器没有提供这个值,默认值为:FtpPermission.None。
- RawPermissions:为此对象接收的原始权限字符串。如果其他的权限为空或者无效,请使用此属性。
- Input:服务器为此对象返回的原始字符串。如果正确解析了上述属性,则有助于调试。
- GetNameListing() - 使用NLST命令返回给定目录中的文件路径列表的简单命令。
- GetObjectInfo() - 获取单个文件或者目录的FtpListItem信息。它包含了类型、创建日期、修改日期、文件大小、权限/chmod和连接目标(如果有的话)。
文件传输
高级API:
- Upload() - 上传一个流或者byte[]到服务器。如果成功的话就返回为true,如果失败或者文件不存在那么返回为false。对于关键的错误会抛出异常。支持非常大的文件上传,因为它的上传是用数据块来实现的。
- Download() - 从服务器下载一个文件到流中或者byte[]中。如果成功的话就返回为true,如果失败或者文件不存在那么返回为false。对于关键的错误会抛出异常。支持非常大的文件下载,因为它的下载是用数据块来实现的。
- UploadFile() - 从本地的文件系统上传一个文件到服务器上。使用FtpExists.Append来恢复继续一个部分的上传。如果成功的话就返回为true,如果失败或者文件不存在那么返回为false。对于关键的错误会抛出异常。支持非常大的文件上传,因为它的上传是用数据块来实现的。可以可选地验证一个文件的哈希值,并且在哈希匹配失败的时候重新尝试传输。
- DownloadFile() - 从服务器上下载一个文件到本地的文件系统。使用FtpExists.Append来恢复继续一个部分的下载。如果成功的话就返回为true,如果失败或者文件不存在那么返回为false。对于关键的错误会抛出异常。支持非常大的文件下载,因为它的下载是用数据块来实现的。可以可选地验证一个文件的哈希值,并且在哈希匹配失败的时候重新尝试传输。
- UploadFiles() - 从本地的文件系统上传多个文件到服务器上的单个文件夹中。返回上传的文件的数目。跳过上传的文件不会被计数。在文件上传的过程中,用户可以自定义处理捕获的异常错误(忽略/终止/抛出)。可以可选地验证一个文件的哈希值,并且在哈希匹配失败的时候重新尝试传输。比使用UploadFile()上传多次的速度快。
- DownloadFiles() - 从服务器上下载多个文件到本地文件系统的一个文件夹中。返回下载的文件的数目。跳过下载的文件不会被计数。在文件下载的过程中,用户可以自定义处理捕获的异常错误(忽略/终止/抛出)。可以可选地验证一个文件的哈希值,并且在哈希匹配失败的时候重新尝试传输。
低级API:
- OpenRead() - (最好使用Download()来下载文件为一个Stream或者一个byte[])打开一个流来读取指定的文件。返回一个标准的stream。在你成功的传输文件之后,请调用GetReply()来读取服务器发送的“OK”指令,并防止套接字上的数据过时。
- OpenWrite() - (最好使用Upload()来上传一个Stream或者一个byte[])打开一个流来写入指定的文件。返回一个标准的stream,任何写入的数据都将覆盖整个文件,如果文件不存在,那么会被创建。在你成功的传输文件之后,请调用GetReply()来读取服务器发送的“OK”指令,并防止套接字上的数据过时。
- OpenAppend() - (最好使用带有FtpExists.Append标志的Upload()来上传一个Stream或者byte[])打开一个流来附加到指定的文件。返回一个标准的stream,任何写入的数据都将附加到文件数据的尾部。在你成功的传输文件之后,请调用GetReply()来读取服务器发送的“OK”指令,并防止套接字上的数据过时。
文件管理
工作目录(相对的路径相对于当前的工作目录):
- GetWorkingDirectory() - 获取当前工作目录的完整路径。
- SetWorkingDirectory() - 设置当前的工作目录的完整路径。所有的相对路径都相对于当前工作目录。
目录:
- DirectoryExists() - 检查服务器上一个目录是不是存在。
- CreateDirectory() - 在服务器上创建一个文件目录。如果不是空的,那么递归删除所有子目录和文件。
- DeleteDirectory() - 删除服务器上指定的目录。如果不是空的,则递归删除所有子目录和文件。
- MoveDirectory() - 将目录从服务器上的一个位置移动到另一个位置。如果FtpExists.OverWrite标志被使用的话,则在移动之前删除目标目录。只对关键错误抛出异常。
文件:
- FileExists() - 检查服务器上是否存在文件。
- DeleteFile() - 删除服务器上的指定文件。
- MoveFile() - 将文件从服务器上的一个目录移动到另一个目录。如果FtpExists.OverWrite标志被使用的话,则在移动之前删除目标文件。只对关键错误抛出异常。
- Rename() - 重命名服务器上的文件/文件夹名称。在大多数情况下不应该使用的低级方法,而是应该使用MoveFile()和MoveDirectory()来重命名文件/文件夹。如果源文件(被重命名)的目标不存在,或者目标(要修改名称的)已经存在,则抛出异常。
- GetModifiedTime() - 获取文件或文件夹的最后的修改日期/时间。结果可能在服务器时区、本时或者是UTC,这取决于type参数。
- SetModifiedTime() - 修改文件或文件夹的最后修改日期/时间。根据输入type参数的不同,输入可以在服务器时区、本地时区或者UTC中。
- GetFileSize() - 获取文件的大小(以字节为单位),如果未找到则为-1。
- DereferenceLink() - 递归地接触对一个符号链接的引用,并且如果找到,则返回完整路径。在放弃这个操作之前,我们通过MaximumDereferenceCount属性来控制递归的深度。
文件权限
大多数的服务器支持的标准命令
- GetChmod() - 获取文件/文件夹的CHMOD权限,如果没有找到则为0。
- GetFilePermissions() - 以带有所有“权限”属性的集合的FtpListItem对象的形式,获取给定文件/文件夹的权限,如果没有找到的话,就返回为null。
只支持安装并启用了CHMOD扩展的UNIX FTP服务器
- Chmod() - 通过给出CHMOD的值,修改给定的文件/文件夹的权限。
- SetFilePermissions() - 通过给出的分离的拥有者/组/其他的值,修改给定的文件/文件夹的权限(FtpPermission枚举)。
文件哈希
(笔记:高级的文件传输API支持在上传/下载之后自动进行文件哈希)
大多数的服务器支持的标准命令
- HashAlgorithms - 如果服务器有的话,获取服务器支持的散列类型(由标志位标识)。
- GetHash() - 使用当前选定的散列算法获取服务器上对象的散列值。支持的算法可用于HashAlgorithms属性。您应该确认它不等于FtpHashAlgorithms.NONE(这意味着服务器不支持HASH命令)。
- GetHashAlgorithm() - 为HASH指令查询服务器当前所选择的哈希算法。
- SetHashAlgorithm() - 为HASH指令选择一个哈希算法,并将这个选择的算法存储在服务器上。
仅由某些服务器支持的非标准的命令。查看更多
- GetChecksum() - 使用服务器支持的校验和方法(如果有的话)检索给定文件的校验和。所使用的算法以下面的顺序:HASH、MD5、XMD5、XSHA1、XSHA256、XSHA512、XCRC。
- GetMD5() - 检索给定文件的MD5校验和(如果服务器支持)。
- GetXMD5() - 检索给定文件的MD5校验和(如果服务器支持)。
- GetXSHA1() - 检索给定文件的SHA1校验和(如果服务器支持)。
- GetXSHA256() - 检索给定文件的SHA256校验和(如果服务器支持)。
- GetXSHA521() - 检索给定文件的SHA512校验和(如果服务器支持)。
- GetXCRC() - 检索给定文件的CRC32校验和(如果服务器支持)。
工具
请导入FluentFTP来使用这些扩展方法,或者直接在FtpExtensions类中访问它们。
- GetFtpPath(path) - 将指定的本地文件/目录路径转换为有效的FTP文件系统路径。
- GetFtpPath(path,segments) - 通过将指定的段附加到此字符串来创建有效的FTP路径。
- GetFtpDirectoryName(path) - 获取给定文件路径的父目录路径。
- GetFtpFileName(path) - 从路径获取文件名和扩展名(如果扩展名存在的话)。
- GetFtpDate(date,styles) - 尝试将字符串FTP日期表示形式转换为日期时间对象。
- FileSizeToString(bytes) - 将文件大小(以字节为单位)转换为字符串表示形式(例如,12345转换为12.3 KB)。
请直接访问FtpClient类下的这些静态方法。
- GetPublicIP() - 使用Ipify服务计算您电脑的公共IP地址。如果你在连接在路由器网络中或没有一个静态的IP地址。
日志
有关日志和调试的帮助,请参阅FAQ的条目。
- client.OnLogEvent - FtpClient的一个属性。分配给这个属性一个回调函数,那么这个回调会在每次记录信息的时候被触发。
- FtpTrace.LogFunctions - 在记录日志的时候,是否记录高级函数的调用。默认值为:true
- FtpTrace.LogIP - 在记录日志的时候,是否将服务器IP地址进行记录。默认值为:true
- FtpTrace.LogUserName - 在记录日志的时候,是否将用户的名称进行记录。默认值为:true
- FtpTrace.LogPassword - 在记录日志的时候,是否将密码进行记录。默认值为:false
- FtpTrace.LogPrefix - 所有的日志信息之前都使用“FluentFTP”前缀。默认值为:false
- FtpTrace.WriteLine - 将消息或错误记录到所有已注册的侦听器。
仅.NET Standard可用
- FtpTrace.LogToConsole - 是否应该将FTP通信(communication)记录到控制台(Console)。默认值为:false
- FtpTrace.LogToFile - 是否设置一个文件的路径,来将所有的FTP通信(communication)来附加到这个文件中。默认值为:false
仅.NET Framework可用
- FtpFrace.FlushOnWrite - 是否在写入每个命令后刷新跟踪侦听器。默认值为:true
- FtpFrace.AddListener - 向系统中(指的是FluentFTP)添加一个日志处理程序。了解更多
- FtpFrace.RemoveListener - 从系统中移除一个日志处理程序。
设置
FTP设置
可以自动检测服务器上的FTP连接设置。
- DataConnectionType - 设置连接是活动还是被动的链接。默认值为:FtpDataConnectionType.AutoPassive(尝试EPSV,然后PASV,最后就放弃)
- Encoding - 与服务器进行通信的时候所使用的的文本编码(ASCII或者UTF8)。ASCII是默认的值,但是在连接的时候,如果服务器支持的话,我们将切换到UTF8编码。手动设置设置这个值的话讲覆盖自动检测。默认值为:Auto。
- InternetProtocolVersions - 在进行连接的时候使用IPV4和/还是IPV6。在名称解析期间返回的所有地址都将被尝试,直到连接成功为止。默认值为:Any。
- UngracefullDisconnection - 服务器在断开连接的时候是否发送QUIT。默认值为:false
- SendHost - 在我手之后立刻发送HOST指令。当你使用共享的主机并且你需要通知你想要连接到那个主机的域的情况下,这个是非常有用的。默认值为:false
- SendHostDomain - 控制哪一个域要被发送HOST命令。如果这个值为null,那么FTP客户端的主机参数将会被发送。默认值为:nulll
主动的FTP设置
- ActivePorts - 设置尝试给主动的FTP连接所使用的端口,如果为null就会自动选择一个端口。默认值为:null。
- AddressResolver - 用于解析本地地址的委托,用于活动数据连接。如果你在路由器的网络下,你可以使用这个,但是端口转发配置为将端口从路由器转发到内部IP。在这种情况下,我们需要发送路由器的IP而不是内部IP。
FPTS设置
请在调用Connect()之前设置这些配置。可以自动地检测这些工作在你服务器上的FTPS连接设置。
- EncrytionMode - 要使用的SSL类型,或者为null。显式是TLS,隐式是SSL。默认值为:FtpEncryptionMode.None。
- DataConnctionEncryption - 指示是否应加密数据通道传输。默认值为:true。
- SslProtocols - 要使用的加密协议。默认值为:SslProtocols.Default。
- SslBuffering - 是否使用SSL缓冲来加速FTP操作期间的数据传输。如果您遇到FTPS/SSL文件传输的随机问题,请关闭此选项。默认值为:FtpsBuffering.Auto。
- ClientCertificates - 在SSL身份验证过程中使用的X509客户端证书。了解更多
- ValidateCertificate - 来验证SSL证书的事件。如果不处理这个事件,并且在验证证书的时候出现错误,那么连接将被终止。
- ValidateAnyCertificate - 接受从服务器接收到的任何SSL证书,并使用ValidateCertificate回调来跳过执行验证。对于Powershell用户是很有用的。默认值为:false。
- ValidateCertificateRevocation - 指示在身份验证期间是否检查了证书撤销列表。在需要维护证书链的验证(the certificate chain validation),但跳过证书的撤销检查(certificate revocation check)时非常有用。默认值为:true。
- PlainTextEncryption - 使用CCC命令,来使得在连接FTPS后立即禁用加密。当你有一个FTP防火墙需要使用纯文本的FTP的时候,这个是很有用的,但是你的服务器要授权FTPS的连接。默认值为:false。
文件清单列表设置
- ListingParser - 要使用的文件清单列表解析器。基于服务器类型会自动的计算,除非被更改。文件列表解析在2017年得到了改进,但是要使用旧的解析例程,请使用FtpParser.Legacy。
- ListingCulture - 用于解析文件清单的区域性。默认值为:CultureInfo.InvariantCulture。
- TimeConversion - 控制如何转换服务器返回的时间戳。默认设置假定所有服务器都返回UTC。默认值为:DateTimeStyles.AssumeUniversal。
- TimeOffset - 服务器和客户机之间的时差,以小时为单位。如果服务器位于阿姆斯特丹,而您在洛杉矶,则时差为9小时。默认值为:0。
- RecursiveList - 如果你的服务器支持一个递归的LIST命令,使用预定义的逻辑进行检查。如果您确定您的服务器支持递归列表,请将此设置为true。(LIST -R)
- BulkListing - 如果为真,则通过一次读取文件清单的多行来提高GetListing的性能。如果为false,则GetListing将逐行读取文件清单。如果GetListing在您的服务器上会有问题,那么请设置为false。默认值为:true。
- BulkListingLength - 在GetListing期间要读取的字节。只有在BulkListing为true的时候才会被执行。默认值为:128。
- MaximumDereferenceCount - 在放弃之前,DereferenceLink()将遵循的符号链接的最大递归深度。默认值为:20。
文件传输设置
- RetryAttempts - 在下载或上传过程中发生验证失败时允许重试的次数。默认值为:1。
- TransferChunkSize - 在上传/下载文件的时候所使用的块的大小(以字节为单位)。默认值为:65536(65KB)。
- UploadRateLimit - 上传速度的限制(以kbyte/s为单位),在高级API中被使用。默认值为:0(无限制)。
- DownloadRateLimit - 下载速度的限制(以kbyte/s为单位),在高级API中被使用。默认值为:0(无限制)。
- UploadDataType - 上传文件以ASCII模式还是二级制模式。默认值为:FtpDataType.Binary。
- DownloadDataType - 下载文件以ASCII模式还是二级制模式。默认值为:FtpDataType.Binary。
- NoopInterval - 在发送NOOP命令之间等待的时间(以毫秒为单位),以便在长时间的文件传输期间保持控制套接字处于活动状态。将这个间隔设置得太低会对性能产生负面影响。将这个间隔设置为0将完全禁用NOOP命令。如果在文件传输期间超时,请减少此设置。请阅读此属性的建议值的PR说明。默认值为:15000(15秒)。
超时设置
- ConnectTimeout - 在放弃之前,等待连接成功的时间(单位毫秒)。默认值为:15000(15秒)。
- ReadTimeout - 在放弃之前,从底层流读取数据的等待时间(单位毫秒)。默认值为:15000(15秒)。
- DataConnectionConnectTimeout - 在放弃之前,等待数据连接建立的时间(单位毫秒)。默认值为:15000(15秒)。
- DataConnectionReadTimeout - 在放弃之前,等待服务器通过数据通道发送数据的时间(单位毫秒)。默认值为:15000(15秒)。
- SocketPollInterval - 在调用套接字上的Poll()以测试连接之前,从上一次套接字活动到开始必须经历的时间(单位毫秒)。将这个间隔设置得太低会对性能产生负面影响。将此间隔设置为0将完全禁用轮询(Poll)。默认值为:15000(15秒)。
嵌套字(socket)设置
- SocketKeepAlive - 设置SocketOption.KeepAlive在将来所有的流的套接字上使用。默认值为:false
- StaleDataCheck - 检查在套接字上是不是有过时的数据(没有被请求的数据)。在某些情况下,控制连接可能会超时,但是在服务器关闭连接之前,它可能会发送一个4xx的意外的响应,并且会以汇报导致同步的错误。为了避免这个问题,Execute()方法在执行命令之前检查套接字上是否有可用的数据。默认值为:true。
- EnableThreadSafeDataConnections - 为每个文件的下载和上传创建一个新的FTP连接。这是一种较慢但线程安全的方法,可使单个控制连接上的异步操作透明。如果FTP服务器每个用户名只允许一个连接,则将此设置为false。了解更多。默认值为:false。
FTP支持
映射表记录了支持的FTP命令和相应的API..
连接指令
指令 |
API |
描述 |
HOST |
SendHost和SendHsotDomain |
在共享主机上标识您的域 |
USER、PASS |
Credentials |
使用用户名和密码登录 |
QUIT |
Disconnect() |
断开连接 |
PASV、EPSV、EPRT |
DataConnectionType |
被动和主动的FTP模式 |
FEAT |
HasFeature() |
获取服务器支持的特性 |
SYST |
GetSystem() |
获取服务器系统类型 |
OPTS UTF8 ON |
Encoding |
支持utf-8文件名 |
OPTS UTF8 OFF |
Encoding,DisableUTF8() |
禁用utf-8文件名 |
SUTH TLS |
EncryptionMode |
切换到TLS/FTPS |
PBSZ、PROT |
EncryptionMode和 DataConnectionEncryption |
配置TLS/FTPS连接 |
CCC |
PlainTextEncryption |
切换到纯文本FTP |
PRET |
Automatic |
预传输(Pre-transfer)文件信息 |
TYPE A |
UploadDataType和 DownloadDataType |
使用ASCII编码传输数据 |
TYPE I |
UploadDataType和 DownloadDataType |
使用二进制编码传输数据 |
文件管理命令
命令 |
API |
描述 |
MLSD |
GetListing() |
获得目录的机器列表 |
LIST |
使用FtpListOption.ForceList标志位的GetListing() |
获取目录文件列表 |
NLST |
GetNameList() 使用FtpListOption.ForceNameList标志位的GetListing() |
获取目录名列表 |
LS |
使用FtpListOption.UseLS标志位的GetListing() |
获取目录文件列表 |
STAT |
使用FtpListOption.UnsStat标志位的GetListing() |
获取目录文件列表 |
MLST |
GetObjectInfo() |
获得文件信息 |
DELE |
DeleteFile() |
删除一个文件 |
MKD |
CreateDirectory() |
创建一个目录 |
SITE MKDIR |
CreateDirectory() |
服务器端递归创建一个目录(ProFTPD) |
RMD |
DeleteDirectory() |
删除一个目录 |
SIT RMDIR |
DeleteDirectory() |
服务器端递归删除一个目录(ProFTPD) |
RMDA |
DeleteDirectory() |
服务器端递归删除一个目录(Serv-U) |
CWD |
SetWorkingDirectory() |
改变工作目录 |
PWD |
GetWorkingDirectory() |
获得工作目录 |
SIZE |
GetFileSize() |
获得文件的字节大小 |
MDTM |
GetModifiedTime() 使用FtpListOption.Modify标志位的GetListing() GetObjectInfo()的dateModified |
获得文件的修改日期 |
MFMT |
SetModifiedTime() |
修改文件的修改日期 |
SITE CHMOD |
Chmod()或者SetFilePermissions() |
修改文件的权限 |
RNFR、RNTO |
Rename() MoveFile() |
重命名一个文件或一个目录 移动一个文件和一个目录 |
NOOP |
Upload() UploadFile() Download() DownloadFile() |
在文件传输的时候保持活动状态 |
文件哈希命令
命令 |
API |
描述 |
HASH |
GetHash() |
获取一个文件的哈希值 |
OPTS HASH |
GetHashAlgorithm()/SetHashAlgorithm() |
为哈希命令选择一个哈希算法 |
MD5 |
GetChecksum()或GetMD5() |
获得一个文件的MD5哈希值 |
XMD5 |
GetChecksum()或GetXMD5() |
获得一个文件的MD5哈希值 |
XSHA1 |
GetChecksum()或GetXSHA1() |
获得一个文件的SHA-1哈希值 |
XSHA256 |
GetChecksum()或GetXSHA256() |
获得一个文件的SHA-256哈希值 |
XSHA512 |
GetChecksum()或GetXSHA512() |
获得一个文件的SHA-512哈希值 |
常见问题
如何自动检测正确的链接设置?
使用下面的代码:
FtpClient client = new FtpClient(hostname, username, password);//或者设置Host和Credentials var profiles = client.AutoDetect(); //如果找到任何配置文件,将代码打印到控制台 if(profiles.Count > 0){ var code = profiles[0].ToCode(); Console.WriteLine(code); }
一旦你找一个工作连接配置文件后,使用生成的代码快速连接到你的FTP服务器。
如何自动连接到FTP或FTPS服务器?
使用下面的代码:
FtpClient client = new FtpClient(hostname, username, password);//或者设置Host和Credentials client.AutoConnect();
如何连接SSL/TLS?/如何使用FTPS?
使用下面的代码:
FtpClient client = new FtpClient(hostname, username, password);//或者设置Host和Credentials client.EncryptionMode = FtpEncryptionMode.Explicit; client.SslProtocols = SslProtocols.Tls; client.ValidateCertificate += new FtpSslValidation(OnValidateCertificate); client.Connect(); void OnValidateCertificate(FtpClient control, FtpSslValidationEventArgs e){ //在这里添加逻辑以测试证书是否有效 e.Accept = true; }
如果你连接到服务器有任何的问题,尝试使用其中之一:
让操作系统选择最高和最相关的TLS协议。
client.SslProtocols = Security.Authentication.SslProtocols.None;
防止操作系统使用在.NET Framework中有问题的TLS 1.0。
client.SslProtocols = SslProtocols.Default | SslProtocols.Tls11 | SslProtocols.Tls12;
如果你在Linux上使用并且使用SSL/TLS连接失败,很可能是这个问题。
如何在使用FTPS时验证服务器的证书?
方法一:如果SSL证书没有错误则进行连接。
cleint.ValidanteCertificate += new FtpSslValidation(delegate (FtpClient c, FtpSslValidtionEventArgs e){ if(e.PolicyErrors != System.Net.Security.SslPolicyErrors.None) { e.Accept = false; } else { e.Accept = true; } });
方法二:如果证书与白名单证书匹配,则连接。
首先,您必须发现有效证书的字符串。使用此代码将有效的证书字符串保存到文件中:
cleint.ValidanteCertificate += new FtpSslValidation(delegate (FtpClient c, FtpSslValidtionEventArgs e){ File.WrtieAllText(@”c:\cert.txt”, e.Certificate.GetRawCertDataString()); });
最后,使用这个代码检查收到的证书是否与您信任的证书匹配:
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?
假设您在Azure应用程序服务实例上使用FTP发布服务。
如果您在连接Azure时遇到问题,请确保您没有“只使用FTPS”。根据Azure文档,“仅支持FTPS”不支持TLS 1.0和1.1,这可能会在试图将FluentFTP用于较旧版本的Windows时破坏连接。因此,当您试图连接到一个将会阻塞TLS 1.1的Azure FTP实例时,连接将静默地失败,因为它只接受TLS 1.2。
将设置更改为允许不安全的FTP之后,可以使用显式和隐式SSL模式连接FTPS。
如何连接FTPS,然后切换回纯文本(Plaintext)的FTP?
当你有一个FTP防火墙需要使用初文明的FTP的时候这是非常有用的。我们使用CCC命令指示服务器恢复到FTP。
在调用FtpClient类上的Connect()或任何其他方法之前设置此选项。
client.PlainTextEncryption = true;
如何连接SFTP?
SFTP不被支持,因为它是SSH下的FTP,一个完全不一样的协议。请使用SSH.NET。
如何中使用匿名的FTP账户登录?/我在登录的时候遇到错误但是我可以在Firefox/Filezilla中正常登录
不设置Credentials属性,我们可以用匿名的身份登录。或者您可以手动指定以下内容:
client.Credentials = new NetworkCredential("anonymous", "anonymous");
如何使用FTP代理登录?
创建一个FtpClientHttpProxy或者FtpClientUserAtHostProxy的对象实例,然后按照往常一样使用FTP的属性和方法。
如何追踪文件的传输进度?
所有的高级的方法都提供了一个progress的参数,被使用来跟踪上传或者下载的进度。
在使用之前,先创建一个回调的方法来提供给上传/下载的方法。它将随着FtpProgress对象被调用,其中包含传输的百分比和各种统计数据。
如果你创建在你WinForm程序的UI中,可以创建一个Minimum = 0并且Maximum = 100的ProgressBar。
使用异步的API:
//接受一个FtpProgress对象的回调方法 Progress<FtpProgress> progress = new Progress<FtpProgress>(x => { //当进度未知的时候,会收到-1 if(x.Progress < 0)
{ progressBar.IsIndeterminate = true; } else { progressBar.IsIndeterminate = false; progressBar.Value = x; } });
使用同步的API:
//接受一个FtpProgress对象的回调方法 Action<FtpProgress> progress = new Action<FtpProgress>(x => { //当进度未知的时候,会收到-1 if(x.Progress < 0) { progressBar.IsIndeterminate = true; } else { progressBar.IsIndeterminate = false; progressBar.Value = x; } });
现在要调用上传/下载方法并提供您刚才创建的新的progress对象。
使用异步的方式:
await client.DownloadFileAsync(localPath, remotePath, FtpLocalExists.Overwrite, FluentFTP.FtpVerify.Retry, progress);
使用同步的方式:
client.DownloadFile(localPath, remotePath, FtpLocalExists.Overwrite, FluentFTP.FtpVerify.Retry, progress);
对于.NET 2.0的用户,通过IProgress类来实现。你传递的对象的Report()方法将会携带进度的值被调用。
如何上传动态创建的数据?
使用Upload()来上传一个stream或者byte[]。
如何下载数据而不将其保存到磁盘?
使用Download()将数据下载到一个stream或者byte[]中。
如何继续下载一个文件?
使用带有existsMode设置为FtpLocalExists.Append的DownloadFile()或者DownloadFiles()。
//通过比较文件大小和本地文件的大小,只下载文件中缺少的部分 client.DownloadFile(@”C:\MyVideo.mp4”, “/htdocs/MyVideo.mp4”, FtpLocalExists.Append);
其他的配置:
- FtpLocalExists.Skip - 如果本地文件存在,我们将盲目地跳过下载,而不进行任何检查。
- FtpLocalExists.Overwrite - 如果本地文件存在,则重新启动下载并覆盖该文件。
- FtpLocalExists.Append - 如果本地文件存在,我们通过检查本地文件大小来恢复下载,并将丢失的数据追加到文件中。
如何继续上传一个文件?
使用一个新的API UploadFile():
//通过比较文件大小和本地文件的大小,只上传服务器文件中缺少的部分 client.UploadFile(@”C:\bigfile.iso”, “/htdocs/bigfile.iso”, FtpLocalExists.Append);
如何控制上传和下载的速度?
设置UploadRateLimit和DownloadRateLimit属性来控制数据传输的速度。只有高级API才支持同步和异步版本,比如:
- Upload()/Download()
- UploadFile()/DownloadFile()
- UploadFiles()/DownloadFiles()
有关节流的最新改进,请参阅这篇文章。
如何验证文件的哈希值/校验和,如果校验和不匹配,如何重试?
将FtpVerify选项设置添加到UploadFile()或DownloadFile()以启用自动校验和验证。
//上传文件的时候重新尝试设置为3次 client.RetryAttempts = 3; //上传一个文件,在放弃之前或尝试重传3次 client.UploadFile(@"C:\MyVideo.mp4", "/htdocs/MyVideo.mp4", FtpExists.Overwrite, false, FtpVerify.Retry);
所有可能的配置:
- FtpVerify.OnlyChecksum - 验证校验和,根据成功返回真/假。
- FtpVerify.Delete - 验证校验和,如果不匹配就删除目标文件。
- FtpVerify.Retry - 验证校验和,重试复制X次,然后放弃。
- FtpVerify.Retry | FtpVerify.Throw - 验证校验和,重试复制X次,如果仍然不匹配则抛出错误。
- FtpVerify.Retry | FtpVerifyDelete - 验证校验和,重试复制X次,如果仍然不匹配就删除目标文件。
- FtpVerify.Retry | FtpVerifyDelete | FtpVerify.Throw - 验证校验和,重试复制X次,如果仍然不匹配就删除目标文件,然后抛出一个错误
如何追加到一个文件?
使用API Upload():
//将数据追加到一个已经存在的文件中 File.AppendAllText(@"C:\readme.txt", "text to be appended" + Environment.NewLine); //只有readme.txt的新部分将被写入服务器 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(); //从服务器读取成功/失败响应 } } }
如何使用低级的(low-level)API下载文件?
使用API OpenRead():
//创建远程FTP流和本地文件流 using (var remoteFileStream = client.OpenRead(remotePath, FtpDataType.Binary)){ using (var newFileStream = File.Create(localPath)){ //一次读取8KB的数据(你可以增加数量) byte[] buffer = new byte[8 * 1024]; //下载文件到本地的流 int len; while ((len = remoteFileStream.Read(buffer, 0, buffer.Length)) > 0) { newFileStream.Write(buffer, 0, len); } } } //读取FTP响应并防止套接字上的过时数据 client.GetReply();
如果我的服务器不支持UTF-8,如何上传/下载Unicode文件名的文件?
手动设置连接编码,以确保特殊字符正常工作。
默认你应该使用的代码页(codepage)是1252 Windows Western。它支持英语+欧洲字符(重音字符)。
client.Encoding = System.Text.Encoding.GetEncoding(1252); //ANSI代码页1252(Windows Western)
以下是基于你需要的字符集的代码页的完整列表:
- 874 – English + Thai
- 1250 – English + Central Europe
- 1251 – English + Cyrillic (Russian)
- 1252 – English + European (accented characters)
- 1253 – English + Greek
- 1254 – English + Turkish
- 1255 – English + Hebrew
- 1256 – English + Arabic
- 1257 – English + Baltic
- 1258 – English + Vietnamese
GetListing()如何在内部工作?
- 当你调用GetListing(),如果它们被服务器支持,FluentFTP首先会想要去使用机器列表清单(使用MLSD命令)。这些数据是最准确的,并且你可以获取正确的文件大小和修改日期(UTC)。你可以使用client.ListingParser = FtpParser.Machine来强制使用这个模式,并且使用FtpListOption.ForceList标志来禁用它。您还应该包括FtpListOption.Modify标志来获得最精确修改日期(精确到第二个)。
- 如果机器列表清单不被支持,我们退一步使用下面列出的特定于服务器OS的解析器(LIST命令)。你可以强制地使用一个特定的解析器,通过使用client.ListingParser = FtpParser.*。
- Unix解析器:用于例如Pure-FTPd、ProFTPD、vsftpd。如果遇到错误,通过使用client.ListingParser.UnixAlt,你可以尝试使用另一种Unix解析器。
- Windows解析器:用于例如IIS、DOS、Azure、FileZilla服务器。
- VMS解析器:用于例如Vax、VMS、OpenVMS。
- NonStop解析器:用于例如Tandem、HP NonStop Guardian。
- IBM解析器:用于列入IBM OS/400。
如果这些都不能满足你,你还可以退一步使用名称清单列表(NLST命令),它比LIST和MLSD命令要慢很多。这是因为NLST只发送文件名列表,没有任何属性。必须逐个文件地查询服务器的文件大小、修改日期和类型(文件/文件夹)。通过FtpListOption.ForceNameList标志,可以让名称清单列表可以被强制使用。
笔记:一些FTP服务器在列空文件夹的列表清单的时候不返回应答,所以客户端在另一端将没有与服务器沟通的套接字。这些异常在内部被捕获,并返回一个空的文件列表。如果你需要检查这个的捕获的实现,请在FluentFTP项目中搜索FtpMissingSocketException的所有实例。
GetListing()如何返回一个递归的文件列表?
在就版本的FluentFTP中,我们假定所有的服务器都支持通过List -R命令来递归列出文件的列表清单。然而,这导致了各种FTP服务器布置成递归列出清单的许多的问题:GetListing()调用将简单地返回第一个目录的内容,而不包含任何子目录。
因此,自从20.0.0版本,我们尝试去检查FTP服务器的软件,并且如果我们确定它不支持递归列表,我们将自己动手地进行递归。我们开始先假设所有服务器都不支持递归列表,然后将特定的服务器类型列入白名单。
如果您感觉GetListing()在使用递归列出列表清单的时候速度太慢,并且您知道您的FTP服务器支持LIST -R命令,然后请为您的服务器提供支持:
- 找到FtpServer枚举中存在的FTP服务器类型。
- 将FtpClient.RecursiveList()更新为您的服务器类型返回为true。
支持哪种散列命令?
我们支持XCRC、XMD5和XSHA,它们是非标准命令,不包含任何形式的规范。它们不能保证工作,强烈建议您检查FtpClient。在调用这些方法之前,为各自的标志设置功能标志(XCRC、XMD5、XSHA1、XSHA256、XSHA512)。
这里文章中描述的MD5命令支持也已经被添加。在执行命令之前,再次检查FtpFeature.MD5。
对HASH命令的支持已经添加到FluentFTP中。它支持从支持这个功能的服务器上检索SHA-1、SHA-256、SHA-512和MD5散列。返回的FtpHash对象,它有一个具有针对给定流或本地文件检查结果的方法。你可以在这个草案中了解更多关于HASH的信息。
如何在调试时追踪FTP命令?
在程序启动时执行此操作(因为它是静态的,所以对所有FtpClient实例都有效)。
.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地址
如何在调试记录所有的FTP命令到文件中?
在程序启动时执行此操作(因为它是静态的,所以对所有FtpClient实例都有效)。
.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地址
如何将关键错误记录到文件中?
这是生产服务器的推荐配置。仅在.NET Framework版本中被支持。
在程序启动时执行此操作(因为它是静态的,所以对所有FtpClient实例都有效)。
FtpTrace.LogFunctions = false; FtpTrace.AddListener(new TextWriterTraceListener("log_file.txt"){ Filter = new EventTypeFilter(SourceLevels.Error) });
如何禁用函数调用的日志记录?
在程序启动时执行此操作(因为它是静态的,所以对所有FtpClient实例都有效)。
FtpTrace.LogFunctions = false;
如何中日志中省略掉敏感的信息?
使用这些设置来控制日志中包含哪些数据:
- FtpTrace.LogUserName - 是否记录FTP的用户名
- FtpTrace.LogPassword - 是否记录FTP的密码
- FtpTrace.LogIP - 是否记录FTP的服务器IP地址
如何使用像NLog这样的第三方日志记录框架?
FluentFTP有一个名为“FluentFTP”的内置TraceSource,可用于调试和日志记录。目前,除了.NET Standard之外,所有的.NET Framework版本都可以使用。通过写入到程序或者配置到你的app.config或者web.config都可以将实现任何的TraceListener附加到类库程序中。这将允许直接日志记录或转发到第三方日志记录框架。
大多数跟踪消息的类型为Verbose或Information,通常可以忽略,除非进行调试。大多数被忽略的异常被归类为Warning,但是返回布尔值表示成功/失败的方法,将以Error级别记录失败原因。如果您使用的是.NET Standard,并且设置了DEDUG标志,然后所有日志消息将通过Debug.Write(message)方式发出。
在代码中附加TraceListener:
TraceListener console = ConsoleTraceListener() { Filter = new EventTypeFilter(SourceLevels.Verbose | SourceLevels.ActivityTracking) }; FtpTrace.AddListener(console);
通过配置文件附加:
<system.diagnostics> <trace autoflush="true"></trace> <sources> <source name="FluentFTP"> <listeners> <clear /> <!--附加一个Console控制台监听器--> <add name="console" /> <!--附加一个File监听器--> <add name="file" /> <!--附加一个用户自定义的监听器--> <add name="myLogger" /> <!--附加一个NLog监听器--> <add name="nlog" /> </listeners> </source> </sources> <sharedListeners> <!--定义一个Console控制台监听器--> <add name="console" type="System.Diagnostics.ConsoleTraceListener" /> <!--定义一个File监听器 --> <add name="file" type="System.Diagnostics.TextWriterTraceListener" initializeData="outputFile.log"> <!--只写入错误--> <filter type="System.Diagnostics.EventTypeFilter" initializeData="Error" /> </add> <!--定义一个用户自定义的监听器--> <add name="custom" type="MyNamespace.MyCustomTraceListener /> <!--附加一个NLog监听器--> <add name="nlog" type="NLog.NLogTraceListener, NLog" /> </sharedListeners> </system.diagnostics>
EnableThreadSafeDataConnections做什么?
EnableThreadSafeDataConnections是由最初的作者构建的一个较老的特性。如果为true,那么每当您试图上传/下载文件时,它都会打开一个新的FTP客户端实例(并重新连接到服务器)。它曾经是默认设置,但它严重影响了性能,所以我禁用了它,发现许多问题都得到了解决,性能也得到了恢复。我相信如果开发者想要多线程上传,他们应该启动一个新的BackgroundWorker并在该线程中创建/使用FtpClient。如果你想要并发上传,可以尝试一下。
如何对FluentFTP做一些修改?/如何提交一个拉取请求(a pull reqest)?
首先你必须“fork”FluentFTP,然后对本地版本进行更改,当提交“pull request”请求让我合并你的变化。
- 在这个页面的右上角点击Fork
- 在这里打开你的版本:https://github.com/YOUR_GITHUB_USERNAME/FluentFTP
- 下载Github Desktop并登录你的账户
- 点击File > Clone repository... 并且在列表中选择FluentFTP
- 将想要放置源码的地方,编辑到“本地的路径”,并且点击Clone
- 使用Visual Studio 2017 Community以及更高的版本来对项目进行编辑
- 切换到Github桌面,它现在应该会显示已更改文件的列表
- 输入一个提交的总结记录(左下方),然后点击Commit
- 点击Push to origin(右上方)
- 打开拉取请求页面来创建一个PR
- 点击New pull request(右上方)
- 点击compare across forks(蓝色的链接,右上方)
- 在右边的“head fork”中选择您的用户名
- 点击Create pull request
- 总结你在标题中所做的修改
- 键入有关您在描述中所做更改的详细信息
- 点击Create pull request
- 谢谢!
如何检测正在连接的服务器的类型?
您可以读取ServerType来获得您所连接的FTP服务器软件的确切类型。我们动态根据我们接连到服务器时服务器所发送的欢迎信息(the welcome message),来检测FTP服务器软件。我们目前可以检测如下软件类型:
- PureFTPd
- VsFTPd
- ProFTPD
- WuFTPd
- FileZilla Server
- OpenVMS
- Windows Server/IIS
- Windows CE
- GlobalScape EFT
- HP NonStop/Tandem
- Serv-U
- Cerberus
- CrushFTP
- glFTPd
- Homegate FTP
- BFTPd
- FTP2S3 Gateway
- XLight
- Solaris FTP
- IBM z/OS
您还可以读取ServerOS来获得所连接的FTP服务器的操作系统。我们可以检测如下系统到:
- Windows
- Unix
- VMS
- IBM OS/400
- IBM z/OS
- SunOS
如何使用客户端证书登入FTPS?
添加你的证书到ClientCertificates,然后再调用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();
并确保:
- 您使用的是X509Certificate2对象,而不是不完整的X509Certificate实现。
- 您不使用pem证书,而是使用p12。请查看这篇Stack Overflow thread来获得更多信息。如果您获得的SPPI异常中包含关于意外消息或格式错误消息的内部异常,您可能使用了错误类型的证书。
如何从一个文件捆绑X509证书?
您需要将证书添加到本地存储(local store),然后执行以下操作:
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。我一直无法让X509Certificate证书工作,从我的查阅的资料来看,这是因为它是一个不完整的实现。
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; }
解决问题
在Visual Studio 2010中Fluent安装失败:“System.Runtime”已经为“FluentFTP”定义了一个依赖项
你的VS使用了一个老版本的nuget.exe,所以它不能正确安装最新的FluentFTP。你必须下载nuget.exe 并手动执行下面这些命令:
cd D:\Projects\MyProjectDir
C:\Nuget\nuget.exe install FluentFTP
上传一个带有特殊字符的文件,像是“Caffè.png”,在FTP服务器上,它表现为“Caff?.png”。这个服务器只支持ASCII,但是这个“è”是ASCII。FileZilla可以上传这个文件,并且没有任何问题
手动设置连接编码,以确保特殊字符正常工作。
默认你应该使用的代码页(codepage)是1252 Windows Western。它支持英语+欧洲字符(重音字符)。
client.Encoding = System.Text.Encoding.GetEncoding(1252); //ANSI代码页1252(Windows Western)
如何文件名中含有俄文字母,我无法删除这个文件。但是FileZilla可以删除这个文件,并且没有问题
手动设置连接编码,以确保特殊字符正常工作。
对于俄语,你需要使用代码页1251 Windows Cyrillic
client.Encoding = System.Text.Encoding.GetEncoding(1251); //ANSI代码页1251(Windows Cyrillic)
我总是在我的Azure WebApp中发生TimeoutException异常
首先尝试减少Azure需要的套接字轮询间隔。
client.SocketPollInterval = 1000;
如果这也不管用,那么试着减少超时时间。
client.SocketPollInterval = 1000; client.ConnectTimeout = 2000; client.ReadTimeout = 2000; client.DataConnectionConnectTimeout = 2000; client.DataConnectionReadTimeout = 2000;
如果这些都不起作用,请记住Azure有一个间歇性的bug,在这个bug中,它会在FTP请求期间更改ip地址。连接是使用IP地址A建立的,Azure使用IP地址B进行数据传输,这在很多防火墙上是不允许的。这是一个已知的Azure bug。
许多的命令无法在Windows CE上正常工作
根据MSDN上所说的,Windows CE上的FTP实现是最少的,并通过源代码开放定制。许多高级命令如CHMOD都不受支持。
使用OpenWrite/OpenAppend成功传输单个文件后,后续文件失败,出现一些随机错误,如“格式错误的PASV响应”
您需要在传输完文件之后调用FtpReply status = GetReply(),以确保没有遗留过时的数据,以免打乱后续命令。
在FTPS的登入期间,SSL协商非常缓慢
FluentFTP在.NET Framework的底层使用SslStream。SslStream使用一个windows的特性功能来动态地更新Root CA证书,这可能会导致证书认证过程中的长时间延迟。这可能会在FluentFTP中引起与SocketPollInterval属性相关的问题,该属性用于检查客户机和服务器之间的不合理断开连接。这个MSDN博客讨论了SslStream的问题,并讨论了如何禁用Root CA证书的自动更新。
FluentFTP记录认证所需的时间。如果您认为自己正遭受这个问题的困扰,那么请查看Examples\ debug .cs以获取有关检索调试信息的信息。
无法从传输连接读取数据:远程主机强制关闭了现有连接
这意味着服务器上的 [FTP守护进程(FTP daemon)] 服务没有运行(可能不是这种情况),或者服务当前仍然忙于执行另一个操作。这听起来就像服务器返回一条消息,表明它仍然在执行上一个操作。
尝试减少轮询间隔以确保连接不会超时。
client.SocketPollInterval = 1000;