Make FTP server return files listed by timestamp with Apache FTPClient

Tags: , ,



I have written this below code to connect to a remote FTP Server (vsftp in CentOS 6). (For brevity Exception handling is not shown here)

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();

If there are 100 files in that FTP server, this listFiles() gives the list of file names according to the Alphabetical order.

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

Is there any way to get the files according to the modified time? (i.e. oldest files first). This listFiles() uses LIST command. Is there any other command available to list the files according to the modification time.? Since this is a Linux server, can we send some Linux commands to achieve this?

I have already checked question get latest file from ftp. The problem with this approach is that we have to order the files using a Comparator then rename and move it a different folder (To get them in the modification order). If there are more than 1000 files, sorting them would become a time consuming operation!

Edit:
And more over, retrieving the files and sorting them has another problem. It doesn’t have seconds information when ftpFile.getTimestamp() is used. It is accurate only to minutes.

Answer

There’s no standard way to have the FTP server sort the files according to your (or any) criteria.

Though some FTP servers, notably the ProFTPD and vsftpd, support proprietary flags with the LIST command to sort the entries.

Both these servers support the -t flag to sort the files by a modification time:

LIST -t

Though this is not only non-standard, it actually violates the FTP protocol.

For all options supported by ProFTPD, see its man page:
http://www.proftpd.org/docs/directives/linked/config_ref_ListOptions.html

Note that vsftpd supports only -a, -r, -t, -F and -l with the same meaning as ProFTPD.

The Apache Commons Net has no API to add flags to the LIST command (the only exception, while irrelevant to this question, is the -a flag – which is sent when FTPClient.setListHiddenFiles is set).

You would have to override the FTPClient.getListArguments to inject your own flags.


Though again, I do not see what’s wrong with using Comparator to sort the files. Just make sure you use FTPClient.mlistDir(), which internally uses a modern MLSD command. This way you get precise timestamps, not minute- or worse precision timestamps like with obsolete LISTFTPClient.listFiles().

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

Though, as you commented, the vsftpd does not support MLSD (ProFTPD does). In that case the LIST -t is indeed the only efficient (although again, not standard/portable) way to get precisely sorted files. Except for a time-consuming call of MDTMFTPClient.getModificationTime for each listed file. If you can do without precise timestamps, the same code as above, but with FTPClient.listFiles() will do.

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



Source: stackoverflow