FTP in Java : Today, I needed to connect from my java code to FTP server. Here how things goes on.
Searching for the best FTP API exists will be the first step. You have to define the criteria’s that your choice we be based on. The Criteria’s are:
- Degree of Support (like: forums, mails, FAQ, phone support and documentation).
- License (Just Free, GPL or LGPL, Not Free (For Commercial)).
- First release or age. (Older package means more testing and bigger community).
- Open Source code (It is better to be open source code; it will be more comfortable to you as a developer).
- Monitoring transfer (So you can calculate number of transferred bytes, you can pause transfer and resume it another time).
- Connect throw proxies (support communication throw firewalls using SOCKS (v4, v5)).
- Support of FTP commands like (Listing directories, rename, deleted, move).
- Support threading and multi-able parallel transfer.
- Support for authentication and security protocol like (SFTP - SSH, FTPS).
For FTP servers I have done my learning phase using File-Zilla server.
About Java FTP API, you may ask, does JDK include FTP classes support? The Answer is yes .which is RFC959, it is implemented but it internal and no source provided. You can use it by the URL specification RFC1738.
- Code:
URL url = new URL("ftp://username:[email protected]/file.txt;type=i");
URLConnection urlconnection = url.openConnection();
InputStream InputstreamObj = urlconnection.getInputStream(); OutputStream outputstreamObj = urlconnection.getOutputStream();
I didn’t use it, There many missing features by this why, it just open input and output data streams.
Well , I tested two libraries , the first one is FTP4J and the second one is Zehon .
1. FTP4J is good, it included the features I needed and mainly the FTPS. It also includes resuming upload and download.
http://www.sauronsoftware.it/projects/f ... nual.php#52. Zehon is a good FTP package. One of its advantage that it includes that can upload and download folders which is pretty good way.
http://www.zehon.com/My big challenge was to run the FTPs. The First thing I did, I generated a security certification using FileZilla server tool .The generated certification is .crt and X502 ASCII contains public and private key. Well , my java code need keystore to run .Keystore is a general concept means a store of private keys , public keys pairs saved by passwords . To create this keystore I use keytool.exe which exists in bin folder.
keytool -genkey -alias javaxforums -keyalg RSA -sigalg MD5withRSA -keypass keyPassword -storepass storePassword -storetype JCEKS -keystore javaxforums.jks
Using the command above, I created a keystore of type JCEKS, remember this keystore contains only 1 private key.
Running the code of loading the keystore :
java code
KeyStore ks = KeyStore.getInstance("JCEKS");
ks.load( new FileInputStream( new File("javaxforums.jks") ),"keyPassword".toCharArray());
KeyManagerFactory km = KeyManagerFactory.getInstance( "IbmX509","IBMJSSE2");
km.init(ks,"storePassword".toCharArray());
KeyManager[] kma = km.getKeyManagers();
TrustManagerFactory tm = TrustManagerFactory.getInstance("IbmX509","IBMJSSE2");
tm.init( ks );
TrustManager[] tma = tm.getTrustManagers();
sslContext = SSLContext.getInstance("SSL");
sslContext.init(kma , tma, new SecureRandom());
java code
java.security.UnrecoverableKeyException: Given final block not properly padded
at com.ibm.crypto.provider.y.a(Unknown Source)
at com.ibm.crypto.provider.JceKeyStore.engineGetKey(Unknown Source)
at java.security.KeyStore.getKey(KeyStore.java:196)
at com.ibm.jsse2.wc.<init>(wc.java:80)
at com.ibm.jsse2.ic$a_.engineInit(ic$a_.java:22)
at javax.net.ssl.KeyManagerFactory.init(KeyManagerFactory.java:9)
at FTPJClient.FTPTestClient.<init>(FTPTestClient.java:79)
at FTPJClient.FTPTestClient.main(FTPTestClient.java:195)
Exception in thread "main" java.lang.NullPointerException
at FTPJClient.FTPTestClient.<init>(FTPTestClient.java:123)
at FTPJClient.FTPTestClient.main(FTPTestClient.java:195)
I was getting this error, I discovered that there must be only one private key in keystore and the passwords of private and keystore have to be the same.
After this I got a new error
- Code:
javax.net.ssl.SSLHandshakeException: com.ibm.jsse2.util.g: No trusted certificate found
at com.ibm.jsse2.n.a(n.java:26)
at com.ibm.jsse2.sc.a(sc.java:483)
at com.ibm.jsse2.gb.a(gb.java:19)
at com.ibm.jsse2.gb.a(gb.java:83)
at com.ibm.jsse2.hb.a(hb.java:295)
at com.ibm.jsse2.hb.a(hb.java:92)
at com.ibm.jsse2.gb.n(gb.java:165)
at com.ibm.jsse2.gb.a(gb.java:26)
at com.ibm.jsse2.sc.a(sc.java:389)
at com.ibm.jsse2.sc.g(sc.java:316)
at com.ibm.jsse2.sc.a(sc.java:528)
my solution to this that I need to insert a public key to the keystore so it can be a trust certificate . I made this by editing the .crt filezilla server generate certification, which includes two parts :
- Code:
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
I to the certificate part and I added it to a new file for example certification.crt and I imported it to the keystore using the following command
keytool -import -trustcacerts -alias root -file certification.crt -keystore javaxforums.jks
After this , it is working .
With zehon JCKES keystore type wasn’t working, you can try the default type or JKS while the creation of keystore.
FTPS is a little bit slower than the FTP .This is what I found by expert and this make sense. A note : if you tried to upload the public key to exported from keystore. You get error like : I can’t upload key file .