1、添加依賴的jar包
以gradle添加依賴為例

compile "org.apache.commons:commons-lang3:3.6" compile "commons-net:commons-net:3.6"
2、封裝下FTPClient

package com.moy.demo.common.utils; import org.apache.commons.lang3.StringUtils; 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; import java.io.*; import java.net.UnknownHostException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * <p>Description: [ftp工具類]</p> * Created on 2018/6/4 * * @author 葉向陽 * @version 1.0 */ public class FtpCli { private static final String DEFAULT_CHARSET = "UTF-8"; private static final int DEFAULT_TIMEOUT = 60 * 1000; private static final String DAILY_FILE_PATH = "dailyFilePath"; private final String host; private final int port; private final String username; private final String password; private FTPClient ftpClient; private volatile String ftpBasePath; private FtpCli(String host, String username, String password) { this(host, 21, username, password, DEFAULT_CHARSET); setTimeout(DEFAULT_TIMEOUT, DEFAULT_TIMEOUT, DEFAULT_TIMEOUT); } private FtpCli(String host, int port, String username, String password, String charset) { ftpClient = new FTPClient(); ftpClient.setControlEncoding(charset); this.host = StringUtils.isEmpty(host) ? "localhost" : host; this.port = (port <= 0) ? 21 : port; this.username = StringUtils.isEmpty(username) ? "anonymous" : username; this.password = password; } /** * <p>Description:[創建默認的ftp客戶端]</p> * Created on 2018/6/5 * * @param host 主機名或者ip地址 * @param username ftp用戶名 * @param password ftp密碼 * @return com.moy.demo.common.utils.FtpCli * @author 葉向陽 */ public static FtpCli createFtpCli(String host, String username, String password) { return new FtpCli(host, username, password); } /** * <p>Description:[創建自定義屬性的ftp客戶端]</p> * Created on 2018/6/5 * * @param host 主機名或者ip地址 * @param port ftp端口 * @param username ftp用戶名 * @param password ftp密碼 * @param charset 字符集 * @return com.moy.demo.common.utils.FtpCli * @author 葉向陽 */ public static FtpCli createFtpCli(String host, int port, String username, String password, String charset) { return new FtpCli(host, port, username, password, charset); } /** * <p>Description:[設置超時時間]</p> * Created on 2018/6/5 * * @param defaultTimeout 超時時間 * @param connectTimeout 超時時間 * @param dataTimeout 超時時間 * @author 葉向陽 */ public void setTimeout(int defaultTimeout, int connectTimeout, int dataTimeout) { ftpClient.setDefaultTimeout(defaultTimeout); ftpClient.setConnectTimeout(connectTimeout); ftpClient.setDataTimeout(dataTimeout); } /** * <p>Description:[連接到ftp]</p> * Created on 2018/6/5 * * @author 葉向陽 */ public void connect() throws IOException { try { ftpClient.connect(host, port); } catch (UnknownHostException e) { throw new IOException("Can't find FTP server :" + host); } int reply = ftpClient.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { disconnect(); throw new IOException("Can't connect to server :" + host); } if (!ftpClient.login(username, password)) { disconnect(); throw new IOException("Can't login to server :" + host); } // set data transfer mode. ftpClient.setFileType(FTP.BINARY_FILE_TYPE); // Use passive mode to pass firewalls. ftpClient.enterLocalPassiveMode(); initFtpBasePath(); } /** * <p>Description:[連接ftp時保存剛登陸ftp時的路徑]</p> * Created on 2018/6/6 * * @author 葉向陽 */ private void initFtpBasePath() throws IOException { if (StringUtils.isEmpty(ftpBasePath)) { synchronized (this) { if (StringUtils.isEmpty(ftpBasePath)) { ftpBasePath = ftpClient.printWorkingDirectory(); } } } } /** * <p>Description:[ftp是否處於連接狀態,是連接狀態返回<tt>true</tt>]</p> * Created on 2018/6/5 * * @return boolean 是連接狀態返回<tt>true</tt> * @author 葉向陽 */ public boolean isConnected() { return ftpClient.isConnected(); } /** * <p>Description:[上傳文件到對應日期文件下, * 如當前時間是2018-06-06,則上傳到[ftpBasePath]/[DAILY_FILE_PATH]/2018/06/06/下]</p> * Created on 2018/6/6 * * @param fileName 文件名 * @param inputStream 文件輸入流 * @return java.lang.String * @author 葉向陽 */ public String uploadFileToDailyDir(String fileName, InputStream inputStream) throws IOException { changeWorkingDirectory(ftpBasePath); SimpleDateFormat dateFormat = new SimpleDateFormat("/yyyy/MM/dd"); String formatDatePath = dateFormat.format(new Date()); String uploadDir = DAILY_FILE_PATH + formatDatePath; makeDirs(uploadDir); storeFile(fileName, inputStream); return formatDatePath + "/" + fileName; } /** * <p>Description:[根據uploadFileToDailyDir返回的路徑,從ftp下載文件到指定輸出流中]</p> * Created on 2018/6/6 * * @param dailyDirFilePath 方法uploadFileToDailyDir返回的路徑 * @param outputStream 輸出流 * @author 葉向陽 */ public void downloadFileFromDailyDir(String dailyDirFilePath, OutputStream outputStream) throws IOException { changeWorkingDirectory(ftpBasePath); String ftpRealFilePath = DAILY_FILE_PATH + dailyDirFilePath; ftpClient.retrieveFile(ftpRealFilePath, outputStream); } /** * <p>Description:[獲取ftp上指定文件名到輸出流中]</p> * Created on 2018/6/5 * * @param ftpFileName 文件在ftp上的路徑 如絕對路徑 /home/ftpuser/123.txt 或者相對路徑 123.txt * @param out 輸出流 * @author 葉向陽 */ public void retrieveFile(String ftpFileName, OutputStream out) throws IOException { try { FTPFile[] fileInfoArray = ftpClient.listFiles(ftpFileName); if (fileInfoArray == null || fileInfoArray.length == 0) { throw new FileNotFoundException("File '" + ftpFileName + "' was not found on FTP server."); } FTPFile fileInfo = fileInfoArray[0]; if (fileInfo.getSize() > Integer.MAX_VALUE) { throw new IOException("File '" + ftpFileName + "' is too large."); } if (!ftpClient.retrieveFile(ftpFileName, out)) { throw new IOException("Error loading file '" + ftpFileName + "' from FTP server. Check FTP permissions and path."); } out.flush(); } finally { closeStream(out); } } /** * <p>Description:[將輸入流存儲到指定的ftp路徑下]</p> * Created on 2018/6/6 * * @param ftpFileName 文件在ftp上的路徑 如絕對路徑 /home/ftpuser/123.txt 或者相對路徑 123.txt * @param in 輸入流 * @author 葉向陽 */ public void storeFile(String ftpFileName, InputStream in) throws IOException { try { if (!ftpClient.storeFile(ftpFileName, in)) { throw new IOException("Can't upload file '" + ftpFileName + "' to FTP server. Check FTP permissions and path."); } } finally { closeStream(in); } } /** * <p>Description:[根據文件ftp路徑名稱刪除文件]</p> * Created on 2018/6/6 * * @param ftpFileName 文件ftp路徑名稱 * @author 葉向陽 */ public void deleteFile(String ftpFileName) throws IOException { if (!ftpClient.deleteFile(ftpFileName)) { throw new IOException("Can't remove file '" + ftpFileName + "' from FTP server."); } } /** * <p>Description:[上傳文件到ftp]</p> * Created on 2018/6/6 * * @param ftpFileName 上傳到ftp文件路徑名稱 * @param localFile 本地文件路徑名稱 * @author 葉向陽 */ public void upload(String ftpFileName, File localFile) throws IOException { if (!localFile.exists()) { throw new IOException("Can't upload '" + localFile.getAbsolutePath() + "'. This file doesn't exist."); } InputStream in = null; try { in = new BufferedInputStream(new FileInputStream(localFile)); if (!ftpClient.storeFile(ftpFileName, in)) { throw new IOException("Can't upload file '" + ftpFileName + "' to FTP server. Check FTP permissions and path."); } } finally { closeStream(in); } } /** * <p>Description:[上傳文件夾到ftp上]</p> * Created on 2018/6/6 * * @param remotePath ftp上文件夾路徑名稱 * @param localPath 本地上傳的文件夾路徑名稱 * @author 葉向陽 */ public void uploadDir(String remotePath, String localPath) throws IOException { localPath = localPath.replace("\\\\", "/"); File file = new File(localPath); if (file.exists()) { if (!ftpClient.changeWorkingDirectory(remotePath)) { ftpClient.makeDirectory(remotePath); ftpClient.changeWorkingDirectory(remotePath); } File[] files = file.listFiles(); if (null != files) { for (File f : files) { if (f.isDirectory() && !f.getName().equals(".") && !f.getName().equals("..")) { uploadDir(remotePath + "/" + f.getName(), f.getPath()); } else if (f.isFile()) { upload(remotePath + "/" + f.getName(), f); } } } } } /** * <p>Description:[下載ftp文件到本地上]</p> * Created on 2018/6/6 * * @param ftpFileName ftp文件路徑名稱 * @param localFile 本地文件路徑名稱 * @author 葉向陽 */ public void download(String ftpFileName, File localFile) throws IOException { OutputStream out = null; try { FTPFile[] fileInfoArray = ftpClient.listFiles(ftpFileName); if (fileInfoArray == null || fileInfoArray.length == 0) { throw new FileNotFoundException("File " + ftpFileName + " was not found on FTP server."); } FTPFile fileInfo = fileInfoArray[0]; if (fileInfo.getSize() > Integer.MAX_VALUE) { throw new IOException("File " + ftpFileName + " is too large."); } out = new BufferedOutputStream(new FileOutputStream(localFile)); if (!ftpClient.retrieveFile(ftpFileName, out)) { throw new IOException("Error loading file " + ftpFileName + " from FTP server. Check FTP permissions and path."); } out.flush(); } finally { closeStream(out); } } /** * <p>Description:[改變工作目錄]</p> * Created on 2018/6/6 * * @param dir ftp服務器上目錄 * @return boolean 改變成功返回true * @author 葉向陽 */ public boolean changeWorkingDirectory(String dir) { if (!ftpClient.isConnected()) { return false; } try { return ftpClient.changeWorkingDirectory(dir); } catch (IOException e) { } return false; } /** * <p>Description:[下載ftp服務器下文件夾到本地]</p> * Created on 2018/6/6 * * @param remotePath ftp上文件夾路徑名稱 * @param localPath 本地上傳的文件夾路徑名稱 * @return void * @author 葉向陽 */ public void downloadDir(String remotePath, String localPath) throws IOException { localPath = localPath.replace("\\\\", "/"); File file = new File(localPath); if (!file.exists()) { file.mkdirs(); } FTPFile[] ftpFiles = ftpClient.listFiles(remotePath); for (int i = 0; ftpFiles != null && i < ftpFiles.length; i++) { FTPFile ftpFile = ftpFiles[i]; if (ftpFile.isDirectory() && !ftpFile.getName().equals(".") && !ftpFile.getName().equals("..")) { downloadDir(remotePath + "/" + ftpFile.getName(), localPath + "/" + ftpFile.getName()); } else { download(remotePath + "/" + ftpFile.getName(), new File(localPath + "/" + ftpFile.getName())); } } } /** * <p>Description:[列出ftp上文件目錄下的文件]</p> * Created on 2018/6/6 * * @param filePath ftp上文件目錄 * @return java.util.List<java.lang.String> * @author 葉向陽 */ public List<String> listFileNames(String filePath) throws IOException { FTPFile[] ftpFiles = ftpClient.listFiles(filePath); List<String> fileList = new ArrayList<>(); if (ftpFiles != null) { for (int i = 0; i < ftpFiles.length; i++) { FTPFile ftpFile = ftpFiles[i]; if (ftpFile.isFile()) { fileList.add(ftpFile.getName()); } } } return fileList; } /** * <p>Description:[發送ftp命令到ftp服務器中]</p> * Created on 2018/6/6 * * @param args ftp命令 * @author 葉向陽 */ public void sendSiteCommand(String args) throws IOException { if (!ftpClient.isConnected()) { ftpClient.sendSiteCommand(args); } } /** * <p>Description:[獲取當前所處的工作目錄]</p> * Created on 2018/6/6 * * @return java.lang.String 當前所處的工作目錄 * @author 葉向陽 */ public String printWorkingDirectory() { if (!ftpClient.isConnected()) { return ""; } try { return ftpClient.printWorkingDirectory(); } catch (IOException e) { // do nothing } return ""; } /** * <p>Description:[切換到當前工作目錄的父目錄下]</p> * Created on 2018/6/6 * * @return boolean 切換成功返回true * @author 葉向陽 */ public boolean changeToParentDirectory() { if (!ftpClient.isConnected()) { return false; } try { return ftpClient.changeToParentDirectory(); } catch (IOException e) { // do nothing } return false; } /** * <p>Description:[返回當前工作目錄的上一級目錄]</p> * Created on 2018/6/6 * * @return java.lang.String 當前工作目錄的父目錄 * @author 葉向陽 */ public String printParentDirectory() { if (!ftpClient.isConnected()) { return ""; } String w = printWorkingDirectory(); changeToParentDirectory(); String p = printWorkingDirectory(); changeWorkingDirectory(w); return p; } /** * <p>Description:[創建目錄]</p> * Created on 2018/6/6 * * @param pathname 路徑名 * @return boolean 創建成功返回true * @author 葉向陽 */ public boolean makeDirectory(String pathname) throws IOException { return ftpClient.makeDirectory(pathname); } /** * <p>Description:[創建多個目錄]</p> * Created on 2018/6/6 * * @param pathname 路徑名 * @author 葉向陽 */ public void makeDirs(String pathname) throws IOException { pathname = pathname.replace("\\\\", "/"); String[] pathnameArray = pathname.split("/"); for (String each : pathnameArray) { if (StringUtils.isNotEmpty(each)) { ftpClient.makeDirectory(each); ftpClient.changeWorkingDirectory(each); } } } /** * <p>Description:[關閉流]</p> * Created on 2018/6/6 * * @param stream 流 * @author 葉向陽 */ private static void closeStream(Closeable stream) { if (stream != null) { try { stream.close(); } catch (IOException ex) { // do nothing } } } /** * <p>Description:[關閉ftp連接]</p> * Created on 2018/6/6 * * @author 葉向陽 */ public void disconnect() { if (null != ftpClient && ftpClient.isConnected()) { try { ftpClient.logout(); ftpClient.disconnect(); } catch (IOException ex) { // do nothing } } } }
3、簡單測試下

package com.moy.demo.common.utils; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import static org.junit.Assert.*; /** * <p>Description: [類功能描述]</p> * Created on 2018/6/6 * * @author 葉向陽 * @version 1.0 */ public class FtpCliTest { FtpCli ftpCli; File file; @Before public void before() throws IOException { ftpCli = FtpCli.createFtpCli("192.168.169.xxx", "ftpuser", "ftpuser"); ftpCli.connect(); String fileName = "testFtp.tmp"; file = new File(fileName); file.createNewFile(); } @After public void after() { ftpCli.disconnect(); } @Test public void uploadFileToDailyDir() throws IOException { String path = ftpCli.uploadFileToDailyDir(file.getName(), new FileInputStream(file)); ftpCli.downloadFileFromDailyDir(path , new FileOutputStream(new File("testFtp.txt"))); } }
yexiangyang
moyyexy@gmail.com