views:

568

answers:

2

The listFiles() method of org.apache.commons.net.ftp.FTPClient works fine with Filezilla server on 127.0.0.1 but returns null on the root directory of public FTP servers such as belnet.be.

There is an identical question on the link below but enterRemotePassiveMode() doesn't seem to help. http://stackoverflow.com/questions/2339855/apache-commons-ftpclient-listfiles

Could it be an issue with list parsing? If so, how can go about solving this?

Edit: Here's a directory cache dump:

FileZilla Directory Cache Dump

Dumping 1 cached directories

Entry 1:
Path: /
Server: [email protected]:21, type: 4096
Directory contains 7 items:
  lrw-r--r-- ftp ftp      D          28      2009-06-17   debian
  lrw-r--r-- ftp ftp      D          31      2009-06-17   debian-cd
  -rw-r--r-- ftp ftp                  0 2010-03-04 13:30  keepalive.txt
  drwxr-xr-x ftp ftp      D        4096 2010-02-18 14:22  mirror
  lrw-r--r-- ftp ftp      D           6      2009-06-17   mirrors
  drwxr-xr-x ftp ftp      D        4096      2009-06-23   packages
  lrw-r--r-- ftp ftp      D           1      2009-06-17   pub

Here's my code using a wrapper I've made (testing inside the wrapper produces the same results):

public static void main(String[] args) {        
    FTPUtils ftpUtils = new FTPUtils();
    String ftpURL = "ftp.belnet.be";
    Connection connection = ftpUtils.getFTPClientManager().getConnection( ftpURL );

    if( connection == null ){
        System.out.println( "Could not connect" );
        return; 
    }

    FTPClientManager manager = connection.getFptClientManager();
    FTPClient client = manager.getClient();

    try {
        client.enterRemotePassiveMode();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    if( connection != null ){
        System.out.println( "Connected to FTP" );
        connection.login("Anonymous", "Anonymous");
        if( connection.isLoggedIn() ){
            System.out.println( "Login successful" );
            LoggedInManager loggedin = connection.getLoggedInManager(); 
            System.out.println( loggedin );
            String[] fileList = loggedin.getFileList();

            System.out.println( loggedin.getWorkingDirectory() );

            if( fileList == null || fileList.length == 0 )
                System.out.println( "No files found" );
            else{
                for (String name : fileList ) {
                    System.out.println( name );
                }
            }

            connection.disconnect();

            if( connection.isDisconnected() )
                System.out.println( "Disconnection successful" );
            else
                System.out.println( "Error disconnecting" );
        }else{
            System.out.println( "Unable to login" );
        }
    } else {
        System.out.println( "Could not connect" );
    }
}

Produces this output:

Connected to FTP
Login succesful
utils.ftp.FTPClientManager$Connection$LoggedInManager@156ee8e
null
No files found
Disconnection successful

Inside the wrapper (attempted using both listNames() and listFiles() ):

        public String[] getFileList() {
            String[] fileList = null;
            FTPFile[] ftpFiles = null;

            try {
                ftpFiles = client.listFiles();
                //fileList = client.listNames();
                //System.out.println( client.listNames() );
            } catch (IOException e) {
                return null;
            }

            fileList = new String[ ftpFiles.length ];

            for( int i = 0; i < ftpFiles.length; i++ ){
                fileList[ i ] = ftpFiles[ i ].getName();
            }

            return fileList;
        }

As for FTPClient, it is handled as follows:

public class FTPUtils {

private FTPClientManager clientManager;

public FTPClientManager getFTPClientManager(){
    clientManager = new FTPClientManager();
    clientManager.setClient( new FTPClient() );

    return clientManager;
}
+1  A: 

Have you tried checking that you can list the files using normal FTP client? (For some reason, I cannot even connect to the FTP port of "belnet.be".)

EDIT

According to the javadoc for listFiles(), the parsing is done using the FTPFileEntryParser instance provided by the parser factory. You probably need to figure out which of the parsers matches the FTP server's LIST output and configure the factory accordingly.

Stephen C
Yes. The files on belnet.be show up fine in FileZilla. A few folders in the root appear to be shortcuts or links. I don't know if that could be a problem. I've added a dump of the directory listing.
James P.
Thanks. Also, the ftp address is ftp.belnet.be.
James P.
+1  A: 

Each FTP server has a different file list layout (yes, it's not part of the FTP standard, it's dumb), and so you have to use the correct FTPFileEntryParser, either by specifying it manually, or allowing CommonsFTP to auto-detect it.

Auto-detection usually works fine, but sometimes it doesn't, and you have to specify it explicitly, e.g.

FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);

FTPClient client = FTPClient();
client.configure(conf);

This explicitly sets the expected FTP server type to UNIX. Try the various types, see how it goes. I tried finding out myself, but ftp.belnet.be is refusing my connections :(

skaffman
Thanks. Do you know if it's possible to get the raw list output before it's parsed?Also, Belnet (belgian research network) might be limited to belgian ips. You can try ftp://c64.rulez.org.
James P.
@James: You could, I suppose, provide your own implementation of `FTPFileEntryParser`
skaffman