FTPUtil.java

package com.sintia.ffl.admin.optique.catalogue.util;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;

@Component
public class FTPUtil {

	private static final Logger LOGGER = LoggerFactory.getLogger(FTPUtil.class);

	//@Value("${ftp.host}")
	private String	host;
//	@Value("${ftp.port}")
	private int		port;
//	@Value("${ftp.user}")
	private String	user;
//	@Value("${ftp.pwd}")
	private String	pwd;

	public FTPUtil() {

	}

	public boolean download(String remoteFilePath, String localFilePath) {
		LOGGER.debug("Going to download remoteFilePath : {} to localFilePath : {}", remoteFilePath, localFilePath);
		FTPClient ftpClient = null;
		try (FileOutputStream outputStream = new FileOutputStream(localFilePath)) {
			ftpClient = getConnection();
			//Set the file type to Binary to force FTPClient to keep the line break format (CR/LF vs LF) 
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			if (!ftpClient.retrieveFile(remoteFilePath, outputStream)) {
				LOGGER.error("Can't download the remote file {} to the local file {}, reply code {}", remoteFilePath, localFilePath, ftpClient
					.getReplyString());
				return false;
			} else {
				outputStream.flush();
				return true;
			}
		}
		catch (IOException e) {
			LOGGER.error("Error downloading remote file {} to local file {}", remoteFilePath, localFilePath, e);
			return false;
		}
		finally {
			if (ftpClient != null && ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				}
				catch (IOException ioe) {
					LOGGER.error("Error disconnecting from FTP after downloading remote file {} to local file {}", remoteFilePath, localFilePath, ioe);
				}
			}
		}

	}

	public boolean upload(String remoteFilePath, String localFilePath) {
		LOGGER.debug("Going to upload localFilePath : {} to remoteFilePath : {}", localFilePath, remoteFilePath);

		// TODO Should we delete the file in local once it's been uploaded ?
		File f = new File(localFilePath);
		if (!f.exists()) {
			LOGGER.error("Local file {} not found, can't upload it.", localFilePath);
		}
		FTPClient ftpClient = null;
		try (FileInputStream inputStream = new FileInputStream(localFilePath)) {
			ftpClient = getConnection();
			//Set the file type to Binary to force FTPClient to keep the line break format (CR/LF vs LF)
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
			if (!ftpClient.storeFile(remoteFilePath, inputStream)) {
				LOGGER.error("Can't upload the local file {} to the remote file {}, reply code {}", localFilePath, remoteFilePath, ftpClient.getReplyString());
				return false;
			} else {
				return true;
			}
		}
		catch (IOException e) {
			LOGGER.error("Error uploading the local file {} to the remote file {}", localFilePath, remoteFilePath, e);
			return false;
		}
		finally {
			if (ftpClient != null && ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				}
				catch (IOException ioe) {
					LOGGER.error("Error disconnecting from FTP after uploading file {} to the remote file {}", localFilePath, remoteFilePath, ioe);
				}
			}
		}

	}

	public boolean delete(String remoteFilePath)
		throws SocketException, IOException {
		LOGGER.debug("Going to delete remoteFilePath : {}", remoteFilePath);
		FTPClient ftpClient = null;
		try {
			ftpClient = getConnection();
			if (!ftpClient.deleteFile(remoteFilePath)) {
				LOGGER.error("Can't delete file {} on the FTP, reply code {}", remoteFilePath, ftpClient.getReplyString());
				return false;
			} else {
				return true;
			}
		}
		catch (IOException ioe) {
			LOGGER.error("Error deleting file {} on the FTP", remoteFilePath, ioe);
			return false;
		}
		finally {
			if (ftpClient != null && ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				}
				catch (IOException ioe) {
					LOGGER.error("Error disconnecting from FTP after deleting file {} on the FTP", remoteFilePath, ioe);
				}
			}
		}
	}

	public List<String> list(String remoteDirectoryPath)
		throws SocketException, IOException {
		LOGGER.debug("Going to list files in remoteDirectoryPath : {}", remoteDirectoryPath);
		FTPClient ftpClient = null;
		try {
			ftpClient = getConnection();
			FTPFile[] files = ftpClient.listFiles(remoteDirectoryPath);
			List<String> filesNames = new ArrayList<>();
			for (FTPFile ftpFile : files) {
				// get the last one
				String fileName = ftpFile.getName();
				filesNames.add(fileName);
				LOGGER.debug("File added : {}", fileName);
			}
			return filesNames;
		}
		catch (IOException ioe) {
			LOGGER.error("Error listing files on the FTP, in the directory {}", remoteDirectoryPath, ioe);
			// TODO check if we should return an empty list, or null, or throws an exception ???
			return new ArrayList<>();
		}
		finally {
			if (ftpClient != null && ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				}
				catch (IOException ioe) {
					LOGGER.error("Error disconnecting from FTP after listing files on the FTP, in the directory {}", remoteDirectoryPath, ioe);
				}
			}
		}
	}

	public boolean isPresent(String remoteDirectoryPath) {

		FTPClient ftpClient = null;
		try {
			ftpClient = getConnection();

			FTPFile[] files = ftpClient.listFiles("/" + remoteDirectoryPath);
			return (files.length > 0);
		}
		catch (IOException ioe) {
			LOGGER.error("Error checking the presence of the file {} on the FTP", remoteDirectoryPath, ioe);
			return false;
		}
		finally {
			if (ftpClient != null && ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				}
				catch (IOException ioe) {
					LOGGER.error("Error disconnecting from FTP after checking the presence of the file {} on the FTP", remoteDirectoryPath, ioe);
				}
			}
		}
	}

	private FTPClient getConnection()
		throws SocketException, IOException {
		FTPClient ftpClient = new FTPClient();
		ftpClient.connect(host, port);
		ftpClient.login(user, pwd);
		ftpClient.enterLocalPassiveMode();
		return ftpClient;
	}
}