Checking file existence on FTP server
Asked Answered
C

4

22

Is there an efficient way to check the existence of a file on a FTP server? I'm using Apache Commons Net. I know that I can use the listNames method of FTPClient to get all the files in a specific directory and then I can go over this list to check if a given file exists, but I don't think it's efficient especially when the server contains a lot of files.

Camire answered 7/5, 2012 at 12:36 Comment(0)
D
28

listFiles(String pathName) should work just fine for a single file.

Dumyat answered 7/5, 2012 at 12:54 Comment(2)
Thanks for your fast answer, I check the FTPFile[] array length to know if the file exists.Camire
It may return a lot of data if pathName is a directory containing a lot of files.Toronto
B
18

Using a full path to a file in listFiles (or mlistDir) call, as the accepted answer shows, should indeed work:

String remotePath = "/remote/path/file.txt";
FTPFile[] remoteFiles = ftpClient.listFiles(remotePath);
if (remoteFiles.length > 0)
{
    System.out.println("File " + remoteFiles[0].getName() + " exists");
}
else
{
    System.out.println("File " + remotePath + " does not exists");
}

The RFC 959 in the section 4.1.3 in the part about the LIST command says:

If the pathname specifies a file then the server should send current information on the file.

Though if you are going to check for many files, this will be rather ineffective. A use of the LIST command actually involves several commands, waiting for their responses, and mainly, opening a data connection. Opening a new TCP/IP connection is a costly operation, even more so, when an encryption is used (what is a must these days).

Also LIST command is even more ineffective for testing an existence of a folder, as it results in a transfer of a complete folder contents.


More efficient is to use mlistFile (MLST command), if the server supports it:

String remotePath = "/remote/path/file.txt";
FTPFile remoteFile = ftpClient.mlistFile(remotePath);
if (remoteFile != null)
{
    System.out.println("File " + remoteFile.getName() + " exists");
}
else
{
    System.out.println("File " + remotePath + " does not exists");
}

This method can be used to test an existence of a directory.

MLST command does not use a separate connection (contrary to LIST).


If the server does not support MLST command, you can abuse getModificationTime (MDTM command) or getSize (SIZE command):

String timestamp = ftpClient.getModificationTime(remotePath);
if (timestamp != null)
{
    System.out.println("File " + remotePath + " exists");
}
else
{
    System.out.println("File " + remotePath + " does not exists");
}

This method cannot be used to test an existence of a directory.

Basipetal answered 17/4, 2018 at 11:46 Comment(1)
Please note that as of 3.8.0 of Apache commons-net, both mlistFile and getModificationTime will return null if the used commands (MLST or MDTM) are not recognized by the FTP server (though hiding the possible existing of a file whilst returning null): github.com/apache/commons-net/blob/rel/commons-net-3.8.0/src/… github.com/apache/commons-net/blob/rel/commons-net-3.8.0/src/…Fiddlededee
T
2

The accepted answer did not work for me.

Code did not work:

String remotePath = "/remote/path/file.txt";
FTPFile[] remoteFiles = ftpClient.listFiles(remotePath);

Instead, this works for me:

ftpClient.changeWorkingDirectory("/remote/path");
FTPFile[] remoteFiles = ftpClient.listFiles("file.txt");
Trapan answered 5/7, 2019 at 12:18 Comment(1)
That's just a peculiarity of your particular FTP server. For majority of servers, there's no difference between the two code snippets.Basipetal
F
-1
public boolean isDirectory(String dstPath) throws IOException {
    return ftpsClient.changeWorkingDirectory(dstPath);
}

public boolean exists(String dstPath) throws IOException {
    if (isDirectory(dstPath)) {
        return true;
    }
    FTPFile[] remoteFiles = ftpsClient.listFiles(dstPath);
    return remoteFiles != null && remoteFiles.length > 0;
}
Funerary answered 29/7, 2022 at 6:25 Comment(3)
One wouldn't expect a function like exists to have side effects.Basipetal
I would like to always use absolute path instead of working directoryFunerary
Fine. But please clearly acknowledge this constraint in your answer.Basipetal

© 2022 - 2024 — McMap. All rights reserved.