Uploading a single file to a FTP server is not a tricky thing. However, uploading a whole directory is a different story, as it requires some extra work and effort:

    • The directory being uploaded may have a quite complex structure, i.e. many directories and files nested together, so we should build an algorithm which is able to iterate over the directory’s content recursively (using recursion algorithm).
    • We have to re-create the whole directory structure on the server, then do uploading every single file to its proper location.

In other words, uploading a directory is similar to copy a directory from the local computer to the FTP server, keeping the copied directory’s structure as same as the original one. Here’s the algorithm we’d like to suggest:

    1. List content of the local directory.
    2. For each item in the local directory:
      • If the item is a file, upload the file to the server.
      • If the item is a directory:
        • Create the directory on the server.
        • Upload this sub directory by repeating the step 1, 2 and 3.
    3. Return if the directory is empty or if the last item is processed.

To implement the algorithm above, create a utility class looks like this:

public class FTPUtil {

	public static void uploadDiretory()	throws IOException {

		// code to upload a whole directory...

	}

	public static boolean uploadSingleFile() throws IOException {

		// code to upload a single file to the server...

	}
}

Following is the detailed implementation of the uploadDirectory() method:

/**
 * Upload a whole directory (including its nested sub directories and files)
 * to a FTP server.
 *
 * @param ftpClient
 *            an instance of org.apache.commons.net.ftp.FTPClient class.
 * @param remoteDirPath
 *            Path of the destination directory on the server.
 * @param localParentDir
 *            Path of the local directory being uploaded.
 * @param remoteParentDir
 *            Path of the parent directory of the current directory on the
 *            server (used by recursive calls).
 * @throws IOException
 *             if any network or IO error occurred.
 */
public static void uploadDirectory(FTPClient ftpClient,
		String remoteDirPath, String localParentDir, String remoteParentDir)
		throws IOException {

	System.out.println("LISTING directory: " + localParentDir);

	File localDir = new File(localParentDir);
	File[] subFiles = localDir.listFiles();
	if (subFiles != null && subFiles.length > 0) {
		for (File item : subFiles) {
			String remoteFilePath = remoteDirPath + "/" + remoteParentDir
					+ "/" + item.getName();
			if (remoteParentDir.equals("")) {
				remoteFilePath = remoteDirPath + "/" + item.getName();
			}


			if (item.isFile()) {
				// upload the file
				String localFilePath = item.getAbsolutePath();
				System.out.println("About to upload the file: " + localFilePath);
				boolean uploaded = uploadSingleFile(ftpClient,
						localFilePath, remoteFilePath);
				if (uploaded) {
					System.out.println("UPLOADED a file to: "
							+ remoteFilePath);
				} else {
					System.out.println("COULD NOT upload the file: "
							+ localFilePath);
				}
			} else {
				// create directory on the server
				boolean created = ftpClient.makeDirectory(remoteFilePath);
				if (created) {
					System.out.println("CREATED the directory: "
							+ remoteFilePath);
				} else {
					System.out.println("COULD NOT create the directory: "
							+ remoteFilePath);
				}

				// upload the sub directory
				String parent = remoteParentDir + "/" + item.getName();
				if (remoteParentDir.equals("")) {
					parent = item.getName();
				}

				localParentDir = item.getAbsolutePath();
				uploadDirectory(ftpClient, remoteDirPath, localParentDir,
						parent);
			}
		}
	}
}

And here is the detailed implementation of the uploadSingleFile() method:

/**
 * Upload a single file to the FTP server.
 *
 * @param ftpClient
 *            an instance of org.apache.commons.net.ftp.FTPClient class.
 * @param localFilePath
 *            Path of the file on local computer
 * @param remoteFilePath
 *            Path of the file on remote the server
 * @return true if the file was uploaded successfully, false otherwise
 * @throws IOException
 *             if any network or IO error occurred.
 */
public static boolean uploadSingleFile(FTPClient ftpClient,
		String localFilePath, String remoteFilePath) throws IOException {
	File localFile = new File(localFilePath);

	InputStream inputStream = new FileInputStream(localFile);
	try {
		ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
		return ftpClient.storeFile(remoteFilePath, inputStream);
	} finally {
		inputStream.close();
	}
}

In order to use the above utility class, we create a test program as follows:

import java.io.IOException;

import org.apache.commons.net.ftp.FTPClient;

/**
 * This test program illustrates how to utilize the FTPUtil class in order
 * to upload a whole directory to a FTP server.
 * @author www.codejava.net
 *
 */
public class FTPUploadDirectoryTest {

	public static void main(String[] args) {
		String server = "www.codejava.net";
		int port = 21;
		String user = "username";
		String pass = "password";

		FTPClient ftpClient = new FTPClient();

		try {
			// connect and login to the server
			ftpClient.connect(server, port);
			ftpClient.login(user, pass);

			// use local passive mode to pass firewall
			ftpClient.enterLocalPassiveMode();

			System.out.println("Connected");

			String remoteDirPath = "/Upload";
			String localDirPath = "E:/Test/Download/FTP/Test";

			FTPUtil.uploadDirectory(ftpClient, remoteDirPath, localDirPath, "");

			// log out and disconnect from the server
			ftpClient.logout();
			ftpClient.disconnect();

			System.out.println("Disconnected");
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
}

Supposing you put the Apache Commons Net library jar file into the same directory of the source files, type the following command to compile the utility class and the test program:

javac -cp commons-net-3.6.jar;. FTPUploadDirectoryTest.java

That will also compile the FTPUtil.java file because it is used by the FTPUploadDirectoryTest class.

Type the following command to run the test program:

java -cp commons-net-3.6.jar;. FTPUploadDirectoryTest

If the directory being uploaded E:/Test/Download/FTP/Test has the following structure:

directory structure to upload

Then the test program will produce the following output:

output of the program to upload a whole directory

 

NOTES:

 

Other Java FTP Tutorials:

 


About the Author:

is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.



Attachments:
Download this file (FTPUploadDirectoryTest.java)FTPUploadDirectoryTest.java[Test program]1 kB
Download this file (FTPUtil.java)FTPUtil.java[Utility class]3 kB

Add comment

   


Comments 

#16Nicolas2018-05-31 11:13
thanks a lot! It was very helpful!
Quote
#15Boumediane2018-04-16 06:52
Hello guys what should I put to username & password and how to create an account when I try to upload the jar file I get this error:
Error uploading file: I/O error: Connection refused: connet
Quote
#14rico2018-01-28 21:07
can you guys show how to add the progress bar to this ftp upload directory?
Quote
#13Choncho2017-06-13 10:56
Quoting Shwetha:
530-Login Authentication failed.
. Please check the username and password, as well as port 21 for FTP is active.
Quote
#12susmith surendran2016-08-25 02:13
sir i really want to use this code.
Quote