A couple months ago I wrote a little tool that converts an Excel file to HTML and then uploads it to a remote host via FTPS (that's right, FTP over SSL). There are a few good Java libraries out there for FTP, but I spent hours and hours finding one that supported TSL/SSL and was free. And worked. There are several out there that claim to have this ability, but I've tried most of them, and most of them don't work right out of the box, or at all.
Finally, I found a library called ftp4che. It's free, well-documented, and just works. I'll give you a glimpse of my uploadFile() method:
private boolean uploadFile() {
txtStatus.append("Setting connection properties..." + newLine);
String host = properties.getProperty("host");
String port = properties.getProperty("port");
String user = txtUserName.getText();
String pass = new String(txtPassword.getPassword());
String path = properties.getProperty("path");
Properties pt = new Properties();
pt.setProperty("connection.host", host);
pt.setProperty("connection.port", port);
pt.setProperty("user.login", user);
pt.setProperty("user.password", pass);
pt.setProperty("connection.type", "AUTH_SSL_FTP_CONNECTION");
pt.setProperty("connection.timeout", "10000");
pt.setProperty("connection.passive", "true");
FTPConnection connection = null;
try {
FTPFile fromFile = new FTPFile(htmlFile);
FTPFile toFile = new FTPFile(path, htmlFile.getName());
txtStatus.append("Connecting to " + host + " on port " + port + "..." + newLine);
connection = FTPConnectionFactory.getInstance(pt);
connection.connect();
connection.noOperation();
txtStatus.append("Connected..." + newLine);
try {
txtStatus.append("Deleting old file..." + newLine);
connection.deleteFile(toFile);
} catch (FtpWorkflowException ex) {
connection.noOperation();
}
txtStatus.append("Uploading new file..." + newLine);
connection.uploadFile(fromFile, toFile);
connection.disconnect();
return true;
} catch (Exception ex) {
ex.printStackTrace();
if (connection != null) {
connection.disconnect();
}
txtStatus.append(ex.getMessage() + newLine);
txtStatus.append("Cannot continue..." + newLine);
return false;
}
}
Pretty straightforward, as you can see. You just set up a Properties object with a set of key/value pairs defining the parameters for your connection, including the authentication type, and then just use an FTPConnectionFactory to create a connection. After that, I try deleting the remote file if it already exists, and then upload the new one, with appropriate exception handling of course. Simple and easy, the way it should be.












Nice find !! Had been looking for something like this for a long time. Does it support Explicit FTPS ? Is AUTH_SSL_CONNECTION the same as Explicit SSL?
Posted by Saurabh on April 07, 2008 at 12:08 PM CDT #
Yep, in this case all SSL/TSL connection types are explicit unless otherwise defined as implicit. From the javadocs:
Constants for connection.type:
public static final int FTP_CONNECTION = 1;
public static final int IMPLICIT_SSL_FTP_CONNECTION = 2;
public static final int AUTH_SSL_FTP_CONNECTION = 3; //explicit
public static final int AUTH_TLS_FTP_CONNECTION = 4; //explicit
public static final int IMPLICIT_TLS_FTP_CONNECTION = 5;
Posted by Trevor on April 07, 2008 at 02:52 PM CDT #
Hi This is really a very usefull artcile .I have one question . In the line below where you havementioned as htmlFile ? is ist defined anywhere ? In my sample i have to download a xml file ..how do i specify ?
FTPFile fromFile = new FTPFile(htmlFile);
Posted by Ajay on July 09, 2008 at 03:38 PM CDT #
Hi
How do we implement handshake in ftp4che ? I have a certificate for connecting to the ftp site
Posted by Ajay on July 10, 2008 at 10:22 AM CDT #
Yeah in my example I am uploading an HTML file, and I have it defined as a class attribute (outside the method). It is just a regular java.io.File instance, but the FTPFile class has several constructors you could use (see the javadoc). If you want to download an XML file (or any file), you need to know the full path to that file on the remote server and just use the FTPConnection's downloadFile() method. I'd do something like the following:
//set up connection
FTPConnection conn = FTPConnectionFactory.getInstance(properties);
conn.connect();
//set up FTPFiles
FTPFile fromFile = new FTPFile("/ftpRoot/xmlFiles/folder1", "myFile.xml");
FTPFile toFile = new FTPFile("C:/Users/You/xmlFiles", "myFile.xml");
//download and save
conn.downloadFile(fromFile, toFile);
As for the handshake stuff, I don't believe this library exposes any direct methods to specify certificates. Rather, it relies on the JVM's certificate store, which you can access via the "Security" tab in the Java Control Panel. Here you can import any certificates you like, and they will be available to your Java programs. In Windows this is under "Control Panel", and in any modern Linux it's under "Preferences". Hope that helps.
Posted by Trevor on July 10, 2008 at 02:36 PM CDT #
Hi Terv
Thank u very much for responding to my questions . Really appreciate that .
Well i tried the smiliar thing what yo mentioned . But it is just going on thinking and not downlaoding the files to the specified location i mentioned in my code .
here is the snippet .
FTPFile fromFile = new FTPFile("/FTPUSERS/FTPTEST/", "SubTest.java");
FTPFile toFile = new FTPFile("c:/xmlfiles/", "SubTest.java");
sFTP.downloadFile(fromFile, toFile);
i get this error :
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(Unknown Source)
at com.sun.net.ssl.internal.ssl.InputRecord.readFully(Unknown Source)
at com.sun.net.ssl.internal.ssl.InputRecord.read(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(Unknown Source)
at org.ftp4che.io.SSLSupport.read(SSLSupport.java:136)
at org.ftp4che.io.SocketProvider.read(SocketProvider.java:162)
at org.ftp4che.io.ReplyWorker.readReply(ReplyWorker.java:128)
at org.ftp4che.io.ReplyWorker.readReply(ReplyWorker.java:107)
at org.ftp4che.FTPConnection.sendCommand(FTPConnection.java:356)
at org.ftp4che.FTPConnection.sendPortCommand(FTPConnection.java:855)
at org.ftp4che.FTPConnection.downloadFile(FTPConnection.java:989)
at org.ftp4che.FTPConnection.downloadFile(FTPConnection.java:929)
at FTPTest.main(FTPTest.java:91)
Posted by Ajay on July 16, 2008 at 07:20 PM CDT #
I was getting a "java.net.SocketTimeoutException: Read timed out" error but when I was uploading a file. My problem was that the file I was uploading did not have both carriage returns and line feeds.
Posted by Juan on February 10, 2009 at 04:01 PM CST #
I am getting the following Exception.....
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Logger
at org.ftp4che.FTPConnection.<clinit>(FTPConnection.java:153)
at org.ftp4che.FTPConnectionFactory.getInstance(FTPConnectionFactory.java:233)
at org.ftp4che.FTPConnectionFactory.getInstance(FTPConnectionFactory.java:140)
Posted by sandeep garg on April 01, 2009 at 01:15 AM CDT #
I m getting the following Exception while downloading:
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at org.ftp4che.io.SocketProvider.read(SocketProvider.java:168)
at org.ftp4che.io.ReplyWorker.readReply(ReplyWorker.java:128)
at org.ftp4che.io.ReplyWorker.run(ReplyWorker.java:198)
Exception in thread "main" java.lang.NullPointerException
at org.ftp4che.FTPConnection.sendCommand(FTPConnection.java:351)
at org.ftp4che.FTPConnection.disconnect(FTPConnection.java:317)
at reliance.FTPS.FTPSExample.uploadFile(FTPSExample.java:208)
at reliance.FTPS.FTPSExample.main(FTPSExample.java:45)
Please Advise......
Posted by sandeep on April 01, 2009 at 05:51 AM CDT #
Do you have a firewall enabled? It's possible that the ftp port is getting blocked, based on that stack trace..
Posted by Trevor on April 02, 2009 at 10:03 AM CDT #
Hi:
I have a problem to connect with a implicit SSl with passive mode.
i have this log:
2009-05-27 18:45:32,662 INFO Reply.dumpReply - 257 "/" is current directory.
2009-05-27 18:45:32,723 INFO Reply.dumpReply - 227 Entering Passive Mode (62,81,224,175,7,217)
2009-05-27 18:45:32,804 INFO Reply.dumpReply - 150 Opening ASCII mode data connection for /bin/ls.
2009-05-27 18:46:17,252 INFO Reply.dumpReply - 421 Data connection closed (SSL/TLS negotiation failed).
anyone knows what im doing wrong ?
thx.
Posted by juanmi on May 27, 2009 at 11:48 AM CDT #