John Humphreys
John Humphreys

Reputation: 39224

Using FTP in Java and detecting disconnections

I've used org.apache.commons.net.ftp.FtpClient to create a reliable FTP class that should download multiple files in parallel, and retry on failures.

Strangely enough, I can't seem to get the code to recognize a failure. For example, if I pull my ethernet cable in the middle of a transfer, the code just seems to continue blocking at the:

client.retrieveFile(nextFile, ftpOutputStream);

line. Can someone tell me why it blocks on this line instead of either returning false or throwing an exception? Did I miss setting a timeout or something like that?

try {
    OutputStream ftpOutputStream = new FileOutputStream(fileName);

    System.out.println("Attempting to retrieve file [" + nextFile + "].");
    success = iclient.retrieveFile(nextFile, ftpOutputStream);
    System.out.println("Returned from retrieving file [" + nextFile + "].");

    ftpOutputStream.close();
}

//Can fail due to FTPConnectionClosedException, CopyStreamException, or IOException.  In any case, best course
//of action is to simply create a new connection, log in again, and change back to target directory.
catch(Exception ex) {

    try {
        System.out.println("Error occurred during download, deleting file and restarting.");
        Thread.sleep(1000);

        //Delete the failed file assuming any of it got written to the local drive.
        File f = new File(fileName);                        
        if(f.exists()) {
            System.out.println("Deleting file...");
            f.delete();
        }             

        Thread.sleep(5000);
    }
    catch (InterruptedException iex) {
        System.out.println("Interrupted exceptoin while respoding to failed FTP attempt.");
    }
}

Upvotes: 2

Views: 253

Answers (1)

JohnKlehm
JohnKlehm

Reputation: 2398

"The way to workaround this is to implement your own SocketFactory and set it with SocketClient.setSocketFactory (FTPClient is a subclass of SocketClient). When you implement the SocketFactory, add a setConnectTimeout method or some such. Inside of the createSocket methods, use the J2SE 1.4 connect method with the timeout."

See the "How can I set a connection timeout?" question on the Commons Net FAQ for why this is so.

Upvotes: 1

Related Questions