上次寫完了工具類,那麼而後就是另外一個工具類了。java
1.也就是對ftp上文件的遍歷。apache
這裏我發現了一個問題,下載文件的時候,每次都得從新鏈接,也就是一次鏈接只能下載一個文件。數組
雖然到最後我也沒發現到底爲啥是這樣,可是我本身的測試是的確這樣的。服務器
全部下載的思路我就設置成,第一次鏈接,遍歷出全部FTP服務器上的文件,而後根據遍歷以後的結果進行下載。dom
這裏我又遇到問題了,我通過遍歷須要獲得什麼結果,才能下載,首先文件名字吧。而後文件在ftp的相對路徑。也就是工做空間ide
關於路徑,因爲在commons-net裏面封裝了ftp上文件類就是org.apache.commons.net.ftp.FTPFile工具
可是你會發現,這個類中沒有方法獲得路徑,這就鬱悶了,居然沒有任何方法能後看出來這個文件是什麼路徑。那怎麼知道某個文件的工做空間在什麼地方。因而只能遍歷了。。。測試
(可是到最後你們會發現,我這裏用的遞歸遍歷,消耗的時間太長,若是ftp文件少沒問題,而後數量大了,光遍歷的時間就太長了。。。。。。。因此以後遍歷被拋棄了,解決版本下此說)this
首先我先創建了一個封裝我本身的類,就是封裝了FTP文件的信息包括名字和其全部的工做空間。spa
import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** * * ftp上文件的封裝 * @author houly * */ public class FtpFile implements Serializable { /** * */ private static final long serialVersionUID = -438376767446894227L; /**文件對應的工做空間,自上而下依次*/ private List<String> list = new ArrayList<String>(); /**文件名稱*/ private String fileName ; public FtpFile() { super(); } public FtpFile(List<String> list, String fileName) { super(); this.list = list; this.fileName = fileName; } public List<String> getList() { return list; } public void setList(List<String> list) { this.list = list; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((fileName == null) ? 0 : fileName.hashCode()); result = prime * result + ((list == null) ? 0 : list.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; FtpFile other = (FtpFile) obj; if (fileName == null) { if (other.fileName != null) return false; } else if (!fileName.equals(other.fileName)) return false; if (list == null) { if (other.list != null) return false; } else if (!list.equals(other.list)) return false; return true; } @Override public String toString() { return "FtpFile [fileName=" + fileName + ", list=" + list + "]"; } }
而後就是遍歷方法了。。。
import java.util.ArrayList; import java.util.List; import org.apache.commons.net.ftp.FTPFile; import org.apache.log4j.Logger; import domain.FtpFile; /** * 遍歷ftp上全部文件的工具類 * @author houly * */ public class FtpTraversal { //日誌 private Logger logger = Logger.getLogger(FtpShow.class); //存放遍歷出來文件的集合 private List<FtpFile> list = new ArrayList<FtpFile>(); //ftp工具類 private FtpHelper ftpHelper; public FtpTraversal(FtpHelper ftpHelper) { this.ftpHelper = ftpHelper; } /** * 遍歷出來FTP裏面全部文件 * @param remotePath 當前工做目錄 * @param list 路徑集合 */ public void listAllFiles(String remotePath, List<String> list) { logger.info("開始遍歷"+remotePath+"目錄......"); //判斷是不是開始目錄 if ("/".equals(remotePath) && list == null) { FTPFile[] files = ftpHelper.getFilesList(); List<String> strings = new ArrayList<String>(); strings.add(remotePath); for (int i = 0; i < files.length; i++) { if (files[i].isFile()) { //若是是文件,就保存路徑,放在文件結合當總 getList().add(new FtpFile(strings, files[i].getName())); } else { List<String> s1 = new ArrayList<String>(strings); //把當前工做目錄保存下載 s1.add(files[i].getName()); listAllFiles(files[i].getName(), s1); //返回到父目錄 ftpHelper.changeToParentDir(); } } } else { //把工做目錄跳轉到remotePath下 ftpHelper.changeDir(remotePath); //列出裏面的全部文件 FTPFile[] files = ftpHelper.getFilesList(); //若是文件夾下沒有文件 if (files == null) { // ftpHelper.changeToParentDir(); // list.remove(list.size()-1); // ftpHelper.changeToParentDir(); return; } int flag = 0; for (int i = 0; i < files.length; i++) { //System.out.println(files[i].getName()); if (files[i].isFile()) { //若是是文件 getList().add(new FtpFile(list, files[i].getName())); flag++; } else { //不是文件 List<String> s1 = new ArrayList<String>(list); s1.add(files[i].getName()); //遞歸調用 listAllFiles(files[i].getName(), s1); //返回上級工做空間 ftpHelper.changeToParentDir(); } } //若是目錄下沒有文件,即便空目錄 if (flag == files.length) { // ftpHelper.changeToParentDir(); // list.remove(list.size()-1); return; } } return; } public List<FtpFile> getList() { return list; } public void setList(List<FtpFile> list) { this.list = list; } public FtpHelper getFtpHelper() { return ftpHelper; } public void setFtpHelper(FtpHelper ftpHelper) { this.ftpHelper = ftpHelper; } }
這裏的遞歸其實能夠寫的更好看的,可是時間比較緊急,沒辦法修改還了。請見諒。。
其實這裏的意思就是從根目錄開始,獲得裏面的全部文件,而後若是是目錄進行遞歸,若是是文件那麼保存生成
我本身的FtpFile類,把文件名和工做空間保存下來。
這裏有人會問爲啥工做空間須要一個數組或者List來保存,由於變動工做目錄的時候一次只能變動一個工做空間。。
2.而後就是文件下載了。
其實很簡單,根據遍歷結果,拼成本地目錄,而後調用工具類裏面的文件下載方法,便可。。
public boolean executeDownload() { logger.info("進入FtpDownloadServiceImpl的executeDownload方法"); // 創建FTP鏈接工具類 FtpHelper ftpHelper = new FtpHelper(); // 根據配置文件鏈接FTP服務器 boolean b = ftpHelper.connect(ConfigInfo.getFtpHostName(), ConfigInfo .getPort(), ConfigInfo.getUsername(), ConfigInfo.getPassword()); if (!b) { logger.error("鏈接不上....."); return false; } // 遍歷FTP服務器上全部文件 FtpShow ftpShow = new FtpShow(ftpHelper); ftpShow.listAllFiles("/", null); List<FtpFile> list = ftpShow.getList(); int num = list.size(); logger.info("遍歷ftp目錄裏面文件的個數爲" + num); ftpHelper.disconnect(); String local_downLoad_dir = ConfigInfo.getFtpDownLoadDir(); logger.info("獲得配置文件中下載目錄爲:" + local_downLoad_dir); int flag = 0; //根據遍歷結果從FTP上下載文件 int count = 0; for (FtpFile file : list) { count++; logger.info("開始下載"+num+"個文件中的第"+count+"個文件"); //FTP鏈接 ftpHelper = new FtpHelper(); ftpHelper.connect(ConfigInfo.getFtpHostName(), ConfigInfo.getPort(), ConfigInfo.getUsername(), ConfigInfo .getPassword()); //該文件工做空間集合 List<String> filepath = file.getList(); //文件下載到本地的路徑 String local_path = local_downLoad_dir; // 變動工做目錄 // 組合下載路徑 for (int i = 0; i < filepath.size(); i++) { //若是是空間默認的開始工做空間 if ("/".equals(filepath.get(i))) { local_path += filepath.get(i); } else { //其餘的工做空間 //變動工做空間 ftpHelper.changeDir(filepath.get(i)); //組合本地路徑 local_path += filepath.get(i) + "/"; } } logger.info("組合以後下載目錄爲:" + local_path); //若是本地工做路徑不存在,創建目錄 File local_file = new File(local_path); if (!local_file.exists()) { local_file.mkdirs(); } //進行下載並返回下載結果 Boolean status = ftpHelper.downloadonefile(file .getFileName(), local_path + file.getFileName()); if (!status) flag++; //斷開FTP鏈接 ftpHelper.disconnect(); } logger.info("進入FtpDownloadServiceImpl的executeDownload方法結束"); if (flag != 0) { return false; } return true; }
這個我以爲沒啥好說的了,註釋寫的很清楚了。。。
這只是中間過程當中的一個版本,雖而後來被拋棄了。。。可是還有有點意義的。。
就是遍歷時間太長了。。。