用commons-net包寫Ftp客戶端下載(二)

上次寫完了工具類,那麼而後就是另外一個工具類了。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;
	}

這個我以爲沒啥好說的了,註釋寫的很清楚了。。。

這只是中間過程當中的一個版本,雖而後來被拋棄了。。。可是還有有點意義的。。

就是遍歷時間太長了。。。

相關文章
相關標籤/搜索