【问题标题】:Make FTP server return files listed by timestamp with Apache FTPClient使用 Apache FTPClient 使 FTP 服务器返回按时间戳列出的文件
【发布时间】:2016-07-02 02:52:14
【问题描述】:

我已经编写了以下代码来连接到远程 FTP 服务器(CentOS 6 中的 vsftp)。 (为简洁起见,这里没有展示异常处理)

FTPClient ftpClient = new FTPClient();
ftpClient.setConnectTimeout(20000);
ftpClient.connect(serverip);
ftpClient.enterLocalPassiveMode();
ftpClient.login(username, password);

if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
    ftpClient.disconnect();
    throw new FTPConnectionClosedException("Unable to connect to FTP server...");
}

FTPFile[] filesList = ftpClient.listFiles();
for (FTPFile tmpFile : filesList) {
    if (tmpFile.isDirectory())
        continue;

    // processing the file
}

if (ftpClient.isConnected())
    ftpClient.disconnect();

如果该 FTP 服务器中有 100 个文件,则此 listFiles() 会根据字母顺序给出文件名列表。

A.txt
B.txt
Z.txt
a.txt
z.txt

有没有办法根据修改时间获取文件?(即最旧的文件优先)。这个listFiles() 使用LIST 命令。 有没有其他命令可以根据修改时间列出文件?既然这是一个Linux服务器,我们可以发送一些Linux命令来实现吗?

我已经检查了问题get latest file from ftp。这种方法的问题是我们必须使用Comparator 对文件进行排序,然后重命名并将其移动到不同的文件夹(以修改顺序获取它们)。如果文件超过 1000 个,对它们进行排序将成为一项耗时的操作!

编辑:
而且,检索文件并对其进行排序还有另一个问题。当使用ftpFile.getTimestamp() 时,它没有seconds 信息。它只精确到分钟。

【问题讨论】:

  • @SubOptimal 这与 OP 已有的相同(相似)代码,但用于不同的库(edtFTPj,而不是 Apache Commons)。
  • @MartinPrikryl 我正在寻找一种解决方案,通过它我可以按最后修改的顺序检索列表,而不是获取列表并使用比较器对其进行排序。
  • @MartinPrikryl 我知道它适用于不同的库,但与 OP 的代码相反,它有一个排序工具。在 OPs 代码中看不到。
  • 代码在OP所指的问题中:stackoverflow.com/q/3824983/850848

标签: java ftp apache-commons-net


【解决方案1】:

没有标准的方法可以让 FTP 服务器根据您的(或任何)标准对文件进行排序。

尽管一些 FTP 服务器,尤其是 ProFTPD 和 vsftpd,支持使用 LIST 命令对条目进行排序的专有标志。

这两个服务器都支持-t 标志以按修改时间对文件进行排序:

LIST -t

虽然这不仅不规范,但实际上违反了 FTP 协议。

有关 ProFTPD 支持的所有选项,请参见其手册页:
http://www.proftpd.org/docs/directives/linked/config_ref_ListOptions.html

请注意,vsftpd 仅支持-a-r-t-F-l,含义与 ProFTPD 相同。

Apache Commons Net 没有向LIST 命令添加标志的API(唯一的例外是-a 标志,虽然与这个问题无关,但在设置FTPClient.setListHiddenFiles 时发送)。

您必须覆盖 FTPClient.getListArguments 才能注入您自己的标志。


尽管如此,我看不出使用Comparator 对文件进行排序有什么问题。只要确保您使用FTPClient.mlistDir(),它在内部使用现代MLSD 命令。这样您就可以获得精确的时间戳,而不是像过时的 LIST - FTPClient.listFiles() 这样的分钟或更差的精度时间戳。

FTPFile[] remoteFiles = ftpClient.mlistDir(remotePath);
        
Arrays.sort(remoteFiles,
    Comparator.comparing((FTPFile remoteFile) -> remoteFile.getTimestamp()).reversed());

不过,正如您所评论的,vsftpd 不支持MLSD(ProFTPD 支持)。在这种情况下,LIST -t 确实是获取精确排序文件的唯一有效(尽管同样不是标准/便携式)方法。除了对每个列出的文件进行耗时的 MDTM - FTPClient.getModificationTime 调用。如果您可以不使用精确的时间戳,则可以使用与上面相同的代码,但使用FTPClient.listFiles()

另见Fetching last modified date of a file in FTP server using FTPClient.getModificationTime yields null

【讨论】:

  • 如您所说,通过覆盖getListArguments() 得到它!我使用参数-tr 首先获取最旧的文件。还有一件事! vsftp 服务器不支持MLSD
  • 是的,我忘记了。我已将此添加到我的答案中。
猜你喜欢
  • 2014-11-21
  • 2015-07-06
  • 1970-01-01
  • 2019-05-21
  • 2020-01-29
  • 1970-01-01
  • 2012-12-09
  • 2020-08-06
  • 1970-01-01
相关资源
最近更新 更多