Question

Here's some code I have to upload a file to an FTP server:

private boolean ftpSend(byte[] fileBytes, String filename, HashMap<String, String> endpointAddressData) throws Exception {
    boolean success = false;

    String login = endpointAddressData.get("user");
    String hostname = endpointAddressData.get("host");
    String password = endpointAddressData.get("password");

    String portString = endpointAddressData.get("port");
    int port = (portString == null) ? 21 : Integer.parseInt(portString);

    FTPClient ftpClient = new FTPClient();
    ByteArrayInputStream inputStream = null;
    try {
        ftpClient.setConnectTimeout(10000);
        ftpClient.connect(hostname, port);

        int reply = ftpClient.getReplyCode();

        if(!FTPReply.isPositiveCompletion(reply)) {
            ftpClient.disconnect();

            throw new Exception("FTP server " + hostname + " refused connection.");
        }

        if (password != null) {
            ftpClient.login(login, password);
        } else {
            ftpClient.user(login);
        }

        logger_.debug("FTP - Writing: " + ftpClient.printWorkingDirectory() + "/" + filename + " on host " + endpointAddressData.get("host"));

        inputStream = new ByteArrayInputStream(fileBytes);
        success = ftpClient.storeFile(filename, inputStream);
        inputStream.close();
        success = success && ftpClient.completePendingCommand();

        logger_.debug("FTP - Completed: " + ftpClient.printWorkingDirectory() + "/" + filename + " on host " + endpointAddressData.get("host"));

        ftpClient.disconnect();

    } catch (Exception ex) {
        success = false;

        logger_.error("An error occurred during FTP upload to " + endpointAddressData.get("host") + ".", ex);
    } finally {
        if (ftpClient.isConnected()) {
            ftpClient.abort();
            ftpClient.disconnect();
        }

        if (inputStream != null) {
            inputStream.close();
        }

        return success;
    }
}

When I run it with some test data, the upload clearly completes successfully (here's the FTP server log):

(000009)01/05/2014 12:13:09 PM - (not logged in) (127.0.0.1)> USER ######
(000009)01/05/2014 12:13:09 PM - (not logged in) (127.0.0.1)> 331 Password required for ######
(000009)01/05/2014 12:13:09 PM - (not logged in) (127.0.0.1)> PASS ########
(000009)01/05/2014 12:13:09 PM - anonymous (127.0.0.1)> 230 Logged on
(000009)01/05/2014 12:13:09 PM - anonymous (127.0.0.1)> PWD ########
(000009)01/05/2014 12:13:09 PM - anonymous (127.0.0.1)> 257 "/" is current directory.
(000009)01/05/2014 12:13:09 PM - anonymous (127.0.0.1)> PORT 127,0,0,1,250,242
(000009)01/05/2014 12:13:09 PM - anonymous (127.0.0.1)> 200 Port command successful
(000009)01/05/2014 12:13:09 PM - anonymous (127.0.0.1)> STOR testFTP1.txt
(000009)01/05/2014 12:13:09 PM - anonymous (127.0.0.1)> 150 Opening data channel for file upload to server of "/testFTP1.txt"
(000009)01/05/2014 12:13:09 PM - anonymous (127.0.0.1)> 226 Successfully transferred "/testFTP1.txt"
(000009)01/05/2014 12:15:10 PM - anonymous (127.0.0.1)> 421 Connection timed out.
(000009)01/05/2014 12:15:10 PM - anonymous (127.0.0.1)> disconnected.

What am I doing wrong?

Was it helpful?

Solution

After stepping through in the debugger, I found out that the ftpClient.completePendingCommand() call was causing the timeout. I guess the command was already completed and it was waiting for the next command indefinitely. I commented out that line and the code completed easily.

From the JavaDoc on FTPClient: http://commons.apache.org/proper/commons-net/apidocs/org/apache/commons/net/ftp/FTPClient.html#completePendingCommand()

There are a few FTPClient methods that do not complete the entire sequence of FTP commands to complete a transaction. These commands require some action by the programmer after the reception of a positive intermediate command. After the programmer's code completes its actions, it must call this method to receive the completion reply from the server and verify the success of the entire transaction.

I guess storeFile() (the FTP STOR command) isn't one of those methods.

OTHER TIPS

I had a code with the same problem. I used the code for downloading various files but one of them just stopped on the same line indefinitely, so instead of commenting it out I just put it in a separate thread and joined for its completion for a while. Now everything seems to be working fine. So it would be something like this:

//right after the downloading part is finished
Thread connectionFinilizerThread = new Thread() {
    public void run() {
        try {
            boolean success= client.completePendingCommand();
            if (success) {
                logger.info("success");
            }
            else{
                logger.error("failure");
            }
        } catch (IOException e) {
        }
    }
}
connectionFinilizerThread.start();
try {
    connectionFinilizerThread.join(20000);
} catch (InterruptedException e) {

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top