Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Java FTP Client for File Upload, Download, and Directory Listing

Tech May 18 2

Using Apache Commons Net, Java applications can interact with FTP servers to upload, download, and list files. The following utilities demonstrtae core operations using FTPClient.

package com.li.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

public class FtpUtil {

    public static boolean uploadFile(String host, int port, String user, String pass,
            String baseDir, String subPath, String targetName, InputStream dataStream) {
        FTPClient client = new FTPClient();
        try {
            client.connect(host, port);
            if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
                client.disconnect();
                return false;
            }
            if (!client.login(user, pass)) {
                client.disconnect();
                return false;
            }

            client.enterLocalPassiveMode();
            client.setFileType(FTP.BINARY_FILE_TYPE);

            String fullPath = baseDir + subPath;
            if (!client.changeWorkingDirectory(fullPath)) {
                String[] parts = subPath.split("/");
                String currentPath = baseDir;
                for (String part : parts) {
                    if (part == null || part.isEmpty()) continue;
                    currentPath += "/" + part;
                    if (!client.changeWorkingDirectory(currentPath)) {
                        if (!client.makeDirectory(currentPath)) {
                            return false;
                        }
                        client.changeWorkingDirectory(currentPath);
                    }
                }
            }

            boolean stored = client.storeFile(targetName, dataStream);
            dataStream.close();
            client.logout();
            return stored;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            if (client.isConnected()) {
                try {
                    client.disconnect();
                } catch (IOException ex) {
                    // ignore
                }
            }
        }
    }

    public static boolean downloadFile(String host, int port, String user, String pass,
            String remoteDir, String fileName, String localDir) {
        FTPClient client = new FTPClient();
        try {
            client.connect(host, port);
            if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
                client.disconnect();
                return false;
            }
            if (!client.login(user, pass)) {
                client.disconnect();
                return false;
            }

            client.enterLocalPassiveMode();
            if (!client.changeWorkingDirectory(remoteDir)) {
                return false;
            }

            FTPFile[] files = client.listFiles();
            for (FTPFile file : files) {
                if (file.isFile() && file.getName().equals(fileName)) {
                    File localFile = new File(localDir, fileName);
                    try (OutputStream out = new FileOutputStream(localFile)) {
                        client.retrieveFile(fileName, out);
                    }
                    client.logout();
                    return true;
                }
            }
            client.logout();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            if (client.isConnected()) {
                try {
                    client.disconnect();
                } catch (IOException ex) {
                    // ignore
                }
            }
        }
    }
}

For listing directory contents recursively:

package com.li.utils;

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

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class FTPDirectoryLister {
    private final FTPClient ftp;
    private final List<String> filePaths;

    public FTPDirectoryLister() {
        this.ftp = new FTPClient();
        this.filePaths = new ArrayList<>();
    }

    public boolean connectAndLogin(String host, int port, String username, String password) throws IOException {
        ftp.connect(host, port);
        if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
            ftp.disconnect();
            return false;
        }
        boolean loggedIn = ftp.login(username, password);
        if (loggedIn) {
            ftp.enterLocalPassiveMode();
            ftp.setControlEncoding("UTF-8");
        } else {
            ftp.disconnect();
        }
        return loggedIn;
    }

    public void listFilesRecursively(String dirPath) throws IOException {
        if (!dirPath.endsWith("/")) {
            dirPath += "/";
        }
        ftp.changeWorkingDirectory(dirPath);
        FTPFile[] items = ftp.listFiles();
        for (FTPFile item : items) {
            if (item.isFile()) {
                filePaths.add(dirPath + item.getName());
            } else if (item.isDirectory()) {
                filePaths.add(dirPath + item.getName() + "/");
                // Uncomment to recurse into subdirectories:
                // listFilesRecursively(dirPath + item.getName());
            }
        }
    }

    public List<String> getFilePaths() {
        return new ArrayList<>(filePaths);
    }

    public void disconnect() throws IOException {
        if (ftp.isConnected()) {
            ftp.disconnect();
        }
    }
}

When the FTP user's root is /home/uftp, paths passed to changeWorkingDirectory() should be relative to that root. For example, to access /home/uftp/public, use changeWorkingDirectory("/public").

Passive mode (enterLocalPassiveMode()) is typically required to avoid firewall issues on the client side.

Tags: Java

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.