import it.sauronsoftware.ftp4j.FTPClient;import it.sauronsoftware.ftp4j.FTPException;import it.sauronsoftware.ftp4j.FTPFile;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import java.net.URISyntaxException;import java.net.URL;import java.util.Arrays;import java.util.Comparator;import java.util.Properties;import java.util.logging.Logger;import org.apache.commons.lang.StringUtils;public class Ftp4jFtpClient{private static Ftp4jFtpClient ftp;/** * FTP服務地址 */private static String ADDRESS;/** * FTP登入使用者名稱 */private static String USERNAME;/** * FTP登入密碼 */private static String PASSWORD;static {Properties pro = new Properties();FileInputStream in;try{String filePath = Ftp4jFtpClient.class.getClassLoader().getResource("/").toURI().getPath() + "ftpserver.properties";in = new FileInputStream(filePath);pro.load(in);ADDRESS = pro.getProperty("ftp_server_address");USERNAME = pro.getProperty("ftp_server_username");PASSWORD = pro.getProperty("ftp_server_password");in.close();}catch (FileNotFoundException e){e.printStackTrace();}catch (IOException e){e.printStackTrace();}catch (URISyntaxException e){e.printStackTrace();}}/** * 構造方法 */private Ftp4jFtpClient() {}/** * 執行個體化對象 * * @return */public static Ftp4jFtpClient getInstance() {if (ftp == null) {ftp = new Ftp4jFtpClient();}return ftp;}/** * 擷取FTP用戶端對象 * * @return * @throws Exception */private FTPClient getClient() throws Exception {FTPClient client = new FTPClient();client.setCharset("utf-8");client.setType(FTPClient.TYPE_BINARY);URL url = new URL(Ftp4jFtpClient.ADDRESS);int port = url.getPort() < 1 ? 21 : url.getPort();client.connect(url.getHost(), port);client.login(Ftp4jFtpClient.USERNAME, Ftp4jFtpClient.PASSWORD);return client;}/** * 登出用戶端串連 * * @param client * FTP用戶端對象 * @throws Exception */private void logout(FTPClient client) throws Exception {if (client != null) {try {// 有些FTP伺服器未實現此功能,若未實現則會出錯client.logout(); // 退出登入} catch (FTPException fe) {} catch (Exception e) {throw e;} finally {if (client.isConnected()) { // 中斷連線client.disconnect(true);}}}}/** * 建立目錄 * * @param client * FTP用戶端對象 * @param dir * 目錄 * @throws Exception */private void mkdirs(FTPClient client, String dir) throws Exception {if (dir == null || dir=="") {return;}dir = dir.replace("//", "/");String[] dirs = dir.split("/");String path = "";for (int i = 0; i < dirs.length; i++) {path += dirs[i] + "/";if (!isDirExist(client,path)) { client.createDirectory(path);// 建立目錄 client.changeDirectory(path);// 進入建立的目錄 }}}/** * 擷取FTP目錄 * * @param url * 原FTP目錄 * @param dir * 目錄 * @return * @throws Exception */private URL getURL(URL url, String dir) throws Exception {String path = url.getPath();if (!path.endsWith("/") && !path.endsWith("//")) {path += "/";}dir = dir.replace("//", "/");if (dir.startsWith("/")) {dir = dir.substring(1);}path += dir;return new URL(url, path);}/** * 擷取FTP目錄 * * @param dir * 目錄 * @return * @throws Exception */private URL getURL(String dir) throws Exception {return getURL(new URL(Ftp4jFtpClient.ADDRESS), dir);}/** * 判斷檔案或目錄是否存在 * * @param client * FTP用戶端對象 * @param dir * 檔案或目錄 * @return * @throws Exception */private boolean exists(FTPClient client, String dir) throws Exception {return getFileType(client, dir) != -1;}//檢查目錄是否存在 private static boolean isDirExist(FTPClient client,String dir) { try { client.changeDirectory(dir); } catch (Exception e) { return false; } return true; }/** * 判斷當前為檔案還是目錄 * * @param client * FTP用戶端對象 * @param dir * 檔案或目錄 * @return -1、檔案或目錄不存在 0、檔案 1、目錄 * @throws Exception */private int getFileType(FTPClient client, String dir) throws Exception {FTPFile[] files = null;try {files = client.list(dir);} catch (Exception e) {return -1;}if (files.length > 1) {return FTPFile.TYPE_DIRECTORY;} else if (files.length == 1) {FTPFile f = files[0];if (f.getType() == FTPFile.TYPE_DIRECTORY) {return FTPFile.TYPE_DIRECTORY;}String path = dir + "/" + f.getName();try {int len = client.list(path).length;if (len == 1) {return FTPFile.TYPE_DIRECTORY;} else {return FTPFile.TYPE_FILE;}} catch (Exception e) {return FTPFile.TYPE_FILE;}} else {try {client.changeDirectory(dir);client.changeDirectoryUp();return FTPFile.TYPE_DIRECTORY;} catch (Exception e) {return -1;}}}/** * 上傳檔案或目錄 * * @param dir * 目標檔案 * @param del * 是否刪除源檔案,預設為false * @param file * 檔案或目錄對象數組 * @throws Exception */public void upload(String dir, boolean del, File... files) throws Exception {if (StringUtils.isEmpty(dir) || files == null || files.length==0) {return;}FTPClient client = null;try {client = getClient();mkdirs(client, dir); // 建立檔案夾for (File file : files) {if (file.isDirectory()) { // 上傳目錄uploadFolder(client, getURL(dir), file, del);} else {String current1 = client.currentDirectory();client.changeDirectory(dir);client.changeDirectory("/" + dir + "/");String current2 = client.currentDirectory();client.upload(file); // 上傳檔案if (del) { // 刪除源檔案file.delete();}}}} finally {logout(client);}}/** * 上傳檔案或目錄 * * @param dir * 目標檔案 * @param files * 檔案或目錄對象數組 * @throws Exception */public void upload(String dir, File... files) throws Exception {upload(dir, false, files);}/** * 上傳檔案或目錄 * * @param dir * 目標檔案 * @param del * 是否刪除源檔案,預設為false * @param path * 檔案或目錄路徑數組 * @throws Exception */public void upload(String dir, boolean del, String... paths)throws Exception {if (dir==null || paths == null || paths.length ==0) {return;}File[] files = new File[paths.length];for (int i = 0; i < paths.length; i++) {files[i] = new File(paths[i]);}upload(dir, del, files);}/** * 上傳檔案或目錄 * * @param dir * 目標檔案 * @param paths * 檔案或目錄路徑數組 * @throws Exception */public void upload(String dir, String... paths) throws Exception {upload(dir, false, paths);}/** * 上傳目錄 * * @param client * FTP用戶端對象 * @param parentUrl * 父節點URL * @param file * 目錄 * @throws Exception */private void uploadFolder(FTPClient client, URL parentUrl, File file,boolean del) throws Exception {client.changeDirectory(parentUrl.getPath());String dir = file.getName(); // 目前的目錄名稱URL url = getURL(parentUrl, dir);if (!exists(client, url.getPath())) { // 判斷目前的目錄是否存在client.createDirectory(dir); // 建立目錄}client.changeDirectory(dir);File[] files = file.listFiles(); // 擷取當前檔案夾所有檔案及目錄for (int i = 0; i < files.length; i++) {file = files[i];if (file.isDirectory()) { // 如果是目錄,則遞迴上傳uploadFolder(client, url, file, del);} else { // 如果是檔案,直接上傳client.changeDirectory(url.getPath());client.upload(file);if (del) { // 刪除源檔案file.delete();}}}}/** * 刪除檔案或目錄 * * @param dir * 檔案或目錄數組 * @throws Exception */public void delete(String... dirs) throws Exception {if (dirs == null || dirs.length ==0) {return;}FTPClient client = null;try {client = getClient();int type = -1;for (String dir : dirs) {client.changeDirectory("/"); // 切換至根目錄type = getFileType(client, dir); // 擷取當前類型if (type == 0) { // 刪除檔案client.deleteFile(dir);} else if (type == 1) { // 刪除目錄deleteFolder(client, getURL(dir));}}} finally {logout(client);}}/** * 刪除目錄 * * @param client * FTP用戶端對象 * @param url * FTP URL * @throws Exception */private void deleteFolder(FTPClient client, URL url) throws Exception {String path = url.getPath();client.changeDirectory(path);FTPFile[] files = client.list();String name = null;for (FTPFile file : files) {name = file.getName();// 排除隱藏目錄if (".".equals(name) || "..".equals(name)) {continue;}if (file.getType() == FTPFile.TYPE_DIRECTORY) { // 遞迴刪除子目錄deleteFolder(client, getURL(url, file.getName()));} else if (file.getType() == FTPFile.TYPE_FILE) { // 刪除檔案client.deleteFile(file.getName());}}client.changeDirectoryUp();client.deleteDirectory(url.getPath()); // 刪除目前的目錄}/** * 下載檔案或目錄 * * @param localDir * 本機存放區目錄 * @param dirs * 檔案或者目錄 * @throws Exception */public void download(String localDir, String... dirs) throws Exception {if (dirs==null ||dirs.length ==0) {return;}FTPClient client = null;try {client = getClient();File folder = new File(localDir);if (!folder.exists()) { // 如果本地檔案夾不存在,則建立folder.mkdirs();}int type = -1;String localPath = null;for (String dir : dirs) {client.changeDirectory("/"); // 切換至根目錄type = getFileType(client, dir); // 擷取當前類型if (type == 0) { // 檔案localPath = localDir + "/" + new File(dir).getName();client.download(dir, new File(localPath));} else if (type == 1) { // 目錄downloadFolder(client, getURL(dir), localDir);}}} finally {logout(client);}}/** * 下載檔案夾 * * @param client * FTP用戶端對象 * @param url * FTP URL * @param localDir * 本機存放區目錄 * @throws Exception */private void downloadFolder(FTPClient client, URL url, String localDir)throws Exception {String path = url.getPath();client.changeDirectory(path);// 在本地建立當前下載的檔案夾File folder = new File(localDir + "/" + new File(path).getName());if (!folder.exists()) {folder.mkdirs();}localDir = folder.getAbsolutePath();FTPFile[] files = client.list();String name = null;for (FTPFile file : files) {name = file.getName();// 排除隱藏目錄if (".".equals(name) || "..".equals(name)) {continue;}if (file.getType() == FTPFile.TYPE_DIRECTORY) { // 遞迴下載子目錄downloadFolder(client, getURL(url, file.getName()), localDir);} else if (file.getType() == FTPFile.TYPE_FILE) { // 下載檔案client.download(name, new File(localDir + "/" + name));}}client.changeDirectoryUp();}/** * 擷取目錄下所有檔案 * * @param dir * 目錄 * @return * @throws Exception */public String[] list(String dir) throws Exception {FTPClient client = null;try {client = getClient();client.changeDirectory(dir);String[] values = client.listNames();if (values != null) {// 將檔案排序(忽略大小寫)Arrays.sort(values, new Comparator<String>(){public int compare(String val1, String val2) {return val1.compareToIgnoreCase(val2);}});}return values;} catch(FTPException fe) {// 忽略檔案夾不存在的情況String mark = "code=550";if (fe.toString().indexOf(mark) == -1) {throw fe;}} finally {logout(client);}return new String[0];}}