8

I made a small application that should upload files to an FTP server. The thing is that I used passive mode with the method

enterLocalPassiveMode() 

Recently I was told that no passive mode is allowed on the FTP server, so I should make my application work in active mode. I suppose it couldn't be done by simply changing the method to

enterLocalActiveMode()

What else should I change in the application to ensure it's working in active mode.

Here's a code snippet which makes the connection to the server:

public void connect() throws FTPException {
        try {
            ftpClient.connect(server, port);
            replyCode = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(replyCode)) {

                printText("FTP server refused connection.");
                throw new FTPException("FTP server refused connection.");

            }
            boolean logged = ftpClient.login(user, pass);
            if (!logged) {
                ftpClient.disconnect();
                printText("Could not login to the server.");
                throw new FTPException("Could not login to the server.");
            }

            ftpClient.enterLocalPassiveMode();

        } catch (IOException ex) {
        printText("I/O errortest: " + ex.getMessage());
            throw new FTPException("I/O error: " + ex.getMessage());
        }
    }

Some guidance to what I have to change?

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
plamenbv
  • 96
  • 1
  • 1
  • 5

3 Answers3

10

This is old, but I stumbled onto it trying to solve the issue myself.

You have to call enterLocalPassiveMode() after calling connect() and before calling login().

See my example below which initialises the FTPClient in local passive mode, lists files for a given directory, then closes the connections.

private static FTPClient client;

public static void main(String [] args) {
    
    //initialise the client
    initPassiveClient();
    
    //do stuff
    FTPFile [] files = listFiles("./");
    if( files != null ) {
        logger.info("Listing Files:");
        for( FTPFile f : files) {
            logger.info(f.getName());
        }
    }
    
    //close the client
    close();
}

/**
 * getPassiveClient retrive a FTPClient object that's set to local passive mode
 *
 * @return FTPClient
 */
public static FTPClient initPassiveClient() {
    if( client == null ) {
        logger.info("Getting passive FTP client");
        client = new FTPClient();

        try {

            client.connect(server);
            // After connection attempt, you should check the reply code to verify
            // success.
            int reply = client.getReplyCode();

            if(!FTPReply.isPositiveCompletion(reply)) {
                client.disconnect();
                logger.error("FTP server refused connection.");
                System.exit(0);
            }

            //after connecting to the server set the local passive mode
            client.enterLocalPassiveMode();

            //send username and password to login to the server
            if( !client.login(user, pass) ) {
                logger.error("Could not login to FTP Server");
                System.exit(0);
            }
        } catch (SocketException e) {
            String message = "Could not form socket";
            logger.error(message+"\n", e);
            System.exit(0);
        } catch (IOException e) {
            String message = "Could not connect";
            logger.error(message+"\n", e);
            System.exit(0);
        }
    }
    
    return client;
}

public static void close() {
    if( client == null ) {
        logger.error("Nothing to close, the FTPClient wasn't initialized");
        return;
    }
    
    //be polite and logout & close the connection before the application finishes
    try {
        client.logout();
        client.disconnect();
    } catch (IOException e) {
        String message = "Could not logout";
        logger.error(message+"\n", e);
    }
}

/**
 * listFiles uses the FTPClient to retrieve files in the specified directory
 *
 * @return array of FTPFile objects
 */
private static FTPFile[] listFiles(String dir) {
    if( client == null ) {
        logger.error("First initialize the FTPClient by calling 'initFTPPassiveClient()'");
        return null;
    }
    
    try {
        logger.debug("Getting file listing for current director");
        FTPFile[] files = client.listFiles(dir);

        return files;
    } catch (IOException e) {
        String message = "";
        logger.error(message+"\n", e);
    }
    
    return null;
}
JoSSte
  • 2,953
  • 6
  • 34
  • 54
Cole Pram
  • 101
  • 1
  • 3
0

http://commons.apache.org/proper/commons-net/apidocs/org/apache/commons/net/ftp/FTPClient.html#enterLocalActiveMode()

Not sure if this is the FTPClient you're using but it would appear that enterLocalActiveMode does indeed exist.

Zach Thacker
  • 2,529
  • 1
  • 23
  • 28
  • Yes, this is the FTPClient I'm using, but will this method initiate a connection in active mode without doing anything else in the code? I'm asking because I can't test the connection at the moment since the FTP server is not available. – plamenbv Jan 28 '14 at 16:02
0

FTPClient Documentation states that

public boolean enterRemoteActiveMode(InetAddress host,int port) throws IOException

Set the current data connection mode to ACTIVE_REMOTE_DATA_CONNECTION . Use this method only for server to server data transfers. This method issues a PORT command to the server, indicating the other server and port to which it should connect for data transfers. You must call this method before EVERY server to server transfer attempt. The FTPClient will NOT automatically continue to issue PORT commands. You also must remember to call enterLocalActiveMode() if you wish to return to the normal data connection mode.

Hope this helps!

Keerthivasan
  • 12,760
  • 2
  • 32
  • 53
  • Thank you very much for the anwers - I appreciate it very much!. So instead of using `enterLocalPassiveMode()` I should use `enterRemoteActiveMode(InetAddress host, int port)`. The `host` argument I believe is the address of the server which I'm uploading to. But what about the port? Should it be port 21 or 20? – plamenbv Jan 28 '14 at 16:45
  • Yes, absolutely! It is port 21 by default. But, check it out if your FTP server is configured to run in any other port – Keerthivasan Jan 28 '14 at 17:56
  • I couldn't wait for the FTP server to be turned on, so I quickly made up a `vsftpd` server on mu Linux machine to give a try. Well, the file wasn't uploaded successfully. It was just created on the server and was empty. I used the method the following way: `boolean foo = enterRemoteActiveMode(InetAddress.getByName("XX.XX.XX.XX"), 21)`. Any idea? – plamenbv Jan 28 '14 at 20:01
  • P.S. I enabled active mode of the vsftpd with `pasv_enable=NO`. – plamenbv Jan 28 '14 at 20:07
  • So, i understand that the file is created, but empty - `0 bytes`. Then, check out whether is no write access or any configuration in vsftpd that disables write action – Keerthivasan Jan 29 '14 at 05:01