在一次调用中递归获取所有 FTP directory/file 列表

Getting all FTP directory/file listings recursively in one call

我正在创建一个备份程序,将数据备份到 FTP。为了有效地归档,我需要做几个文件属性比较。现在,我正在使用 FluentFTP 并调用 FtpClient.FileExists FtpClient.GetFileSizeFtpClient.GetModifiedTime 每个文件 。这显然不是很理想。

如果我可以在一次调用中下载 FTP 目录的整个树结构以及文件属性,它将大大提高备份速度。另一种方法是建立一个本地索引,但我必须确保它被正确更新,并且还要考虑到它被破坏的可能性。

除了我自己的解决方案之外,还有什么办法可以做到这一点吗?

FTP 提供这些命令来检索有关远程文件的信息:

  • NLST 检索特定目录中的文件名 – 所有 服务器支持。
  • SIZEMDTM 检索特定文件的大小和修改文件 – 几乎 所有服务器支持。
  • LIST 检索目录列表,包括文件属性 – 所有 服务器都支持,但列表不是标准化的,因此不是真正的机器可读。虽然大多数服务器将支持 *nix 样式列表(如 *nix ls 命令)。虽然每个人都有自己的怪癖。
  • MLSD 检索目录列表,包括机器可读格式的文件属性 – 此命令最少受支持。 *nix vsftpd 和 Windows IIS 特别不支持它。

因此您不必为每个文件 使用FtpClient.GetFileSizeFtpClient.GetModifiedTime 。每个目录使用 FtpClient.GetListing 。如果服务器支持,它在内部使用 MLSD。否则它会退回到 LIST 并尝试解析列表。


一些 FTP 服务器(如 ProFTPD)确实支持非标准的专有 -R 切换到 LIST 命令,这将使它们 return 列出所有子文件夹。 FluentFTP 也支持 (FtpListOption.Recursive)。请注意,FluentFTP 仅将 -RLIST 一起使用,而如果服务器支持,它更喜欢使用 MLSD。因此,要确保使用 LIST -R,您需要同时使用 FtpListOption.RecursiveFtpListOption.ForceList

如果你的服务器不支持-R开关,你必须自己实现递归。或者使用具有 API 的 FTP 客户端。

例如 my WinSCP .NET assembly, you can use Session.EnumerateRemoteFiles:

IEnumerable<RemoteFileInfo> allFiles =
    session.EnumerateRemoteFiles("/", null, EnumerationOptions.AllDirectories);