Sending Files via FTP From Your Java Applications - Part 1 of 2 - Using Commons Net For FTP

Within the enterprise applications that I design and develop, a requirement always comes up to integrate it in some way with an external, 3rd party system. For example, in writing an insurance policy management system, the carriers often want policy details FTP’ed to them. Logistics companies typically FTP EDI files around all day. And most recently at the University for which I work, we have integrated our systems to transmit financial aid data to the government, send information related to book store vouchers to our outsourced bookstore, and we have our student data geocoded to help us analyze what profile of students are enrolling. All of these external providers want the data to be FTP’ed to them.

To meet these requirements, I develop most of my data feeds in Java. Java makes it very easy to get data out of a database, package it up into a file, and FTP it off to its destination. Two of the libraries I find very useful to perform the FTP are the Jakarta Commons Net library for standard FTP transfers, and the JSch (Java Secure Channel) library to do SFTP transfers.

In this post I will show you how easy it is to use the Jakarta Commons Net library to perform FTP transfers. My next post will then show you how to use the JSch library to perform SFTP transfers.



Part 1 of 2 - Using Jakarta Commons Net for FTP Transfers
To use Jakarta Commons Net, you’ll first want to download the library. Go to the Jakarta Commons Net homepage, and download the binary distribution of the library from them. The link directly to the download page is http://jakarta.apache.org/site/downloads/downloads_commons-net.cgi.

You will also need to have Jakarta ORO in your classpath. It can be downloaded directly from http://jakarta.apache.org/site/downloads/downloads_oro.cgi.

Once you download the libraries unzip them and put their appropriate jar files in your classpath. For my example, I am using commons-net-1.4.1.jar and Jakarta-oro-2.0.8.jar.

And now we get to the good stuff. Here is my class that shows how to use the basics of the Commons Net package to perform an FTP transfer:

package com.tima.examples;

import org.apache.commons.net.ftp.*;
import java.io.*;

/**
 * This class is used to demonstrate the usage of the
 * Jakarta Commons Net package
 * 
 * @author  Tim Archer 04/20/07
 * @version $Revision: 1.1 $
 */
public class TestCommonsNet {
    
    /** Creates a new instance of TestCommonsNet */
    public TestCommonsNet() {
    }
    
    /**
     * main - Unit test program
     * @param args Command line arguments
     *
     */
    public static void main(String args[]) {
        try {
            String ftpHost = "ftp.myserver.com";
            String ftpUserName = "tima";
            String ftpPassword = "mypassword";
            String ftpRemoteDirectory = "/home/tarcher/tmp/";
            String fileToTransmit = "c:\\temp\\test.txt";
            
            //Create a Jakarta Commons Net FTP Client object
            FTPClient ftp = new FTPClient();

            //A datatype to store responses from the FTP server
            int reply;
                
            //
            //Connect to the server
            //
            ftp.connect(ftpHost);
            
            //
            // After connection attempt, you should check the reply code to verify
            // success.
            //
            reply = ftp.getReplyCode();    
            if(!FTPReply.isPositiveCompletion(reply)) {
                try {
                    ftp.disconnect();
                } catch (Exception e) {
                    System.err.println("Unable to disconnect from FTP server " +
                                       "after server refused connection. "+e.toString());
                }
                throw new Exception ("FTP server refused connection.");
            }              
            System.out.println("Connected to " + ftpHost + ". "+ftp.getReplyString());
                
            //
            //Try to login
            //
            if (!ftp.login(ftpUserName, ftpPassword)) {
                throw new Exception ("Unable to login to FTP server " +
                                     "using username "+ftpUserName+" " +
                                     "and password "+ftpPassword);
            }

            System.out.println(ftp.getReplyString());
            System.out.println("Remote system is " + ftp.getSystemName());

            //
            //Set our file transfer mode to either ASCII or Binary
            //
            //ftp.setFileType(FTP.ASCII_FILE_TYPE);
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
                
            //
            //Change the remote directory
            //
            if (ftpRemoteDirectory != null && ftpRemoteDirectory.trim().length() > 0) {
                System.out.println("Changing to FTP remote dir: " + ftpRemoteDirectory);
                ftp.changeWorkingDirectory(ftpRemoteDirectory);
                reply = ftp.getReplyCode();
            
                if(!FTPReply.isPositiveCompletion(reply)) {
                    throw new Exception ("Unable to change working directory " +
                                         "to:"+ftpRemoteDirectory);
                }
            }
                
            //
            //Get the file that we will transfer and send it.
            //
            File f = new File(fileToTransmit);
            System.out.println("Storing file as remote filename: " + f.getName());
            boolean retValue = ftp.storeFile(f.getName(), new FileInputStream(f));
            if (!retValue) {
              throw new Exception ("Storing of remote file failed. ftp.storeFile()" +
                                   " returned false.");
            }
                
            
            //
            //Get the list of files on the remote server
            //
            FTPFile files[] = ftp.listFiles();
            reply = ftp.getReplyCode();
            
            if(!FTPReply.isPositiveCompletion(reply)) {
                throw new Exception ("Unable to get list of files to dowload.");
            }
              
            //
            //Log if we have nothing to download
            //
            if (files.length == 0) {
                System.out.println("No files are available for download.");
            }
            //
            //Otherwise download all files and process each file
            //
            else {
                for (int i=0; i<files.length; i++) {
                    System.out.println("Downloading file "+files[i].getName()+" Size:"+files[i].getSize());
                    String outputFileName = "c:\\temp\\"+files[i].getName();
                    f = new File(outputFileName);

                    retValue = ftp.retrieveFile(files[i].getName(), new FileOutputStream(f));
                    if (!retValue) {
                      throw new Exception ("Downloading of remote file "+files[i].getName()+" failed. ftp.retrieveFile() returned false.");
                    }                      
                      
                    //
                    //Remove the file from the FTP server
                    //  
                    /*                      
                      retValue = ftp.deleteFile(files[i].getName());
                      if (!retValue) {
                          log.error ("Unable to delete remote file "+files[i].getName()+". ftp.deleteFile() returned false.");
                      }                      
                    */                      
                }  //end of for loop
            }
              
            //
            //Disconnect from the FTP server
            //
            try {
                //ftp.logout();
                ftp.disconnect();
            } catch (Exception exc) {
                System.err.println("Unable to disconnect from FTP server. " + exc.toString());
            }
            
        } catch (Exception e) {
            System.err.println("Error: "+e.toString());
        }
        
        System.out.println("Process Complete.");
        System.exit(0);
    }    
}

Please take a moment to study the class above. It is a very simple example of using Commons Net to perform various FTP actions. Specifically, it will show you how to:

  • Connect to an FTP server
  • Change to a new remote directory
  • Set the transfer mode
  • Upload a file
  • Get a list of files in the remote directory and download a file.
  • Disconnect from the FTP server.

I dont think I need to explain the class in any more detail. The code in the main() method is pretty self explanatory and commented for you to find out what does what. Plus, the Jakarta team really did a GOOD job in creating a useful library here that is easy to use.

The one thing I will point out is the repeated calls to the method FTPReply.isPositiveCompletion(). You’ll want your program to check the FTP responses after each FTP command is issued to ensure it successfully completed. After all, you wouldn’t want to continue trying to send a file if the login failed.

Tomorrow I will show you how to SFTP files from Java. For now, happy FTP'ing!



Comments

Listing Remote files

Thanks for the example!

One note:

When getting files from remote ftp server FTPClient.retrieveFile() method DOES NOT close stream where the file is written. So you should add something like this to your code:
....
File f = new File(outputFileName);
OutputStream output = new FileOutputStream(f);

boolean retValue = ftp.retrieveFile(files[i].getName(), output);
if (!retValue) {
throw new Exception ("Downloading of remote file "+files[i].getName()+" failed. ftp.retrieveFile() returned false.");
}
try
{
output.flush();
output.close();
}
catch (Exception e)
{
log.warn("Couldn't flush / close ftp destination file stream"+e.getMessage(),e);
}

...

Good catch! Thanks for the

Good catch! Thanks for the tip Anzi, and thanks for reading my blog!

Hi - any chance you could

Hi - any chance you could provide a link to the source file (the code in the article is truncated)? Your ftp articles are extremely timely.

Whoops, I'm sorry. When I

Whoops, I'm sorry. When I posted the code, I have a less than symbol in my for loop. This was causing the HTML to render improperly as it thought it was encountering a closing tag. Take a look at the code now, it all should be there.

I hope you find it useful, and thanks for visiting my site!

v2.0