上次写完了工具类,那么而后就是另外一个工具类了。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; }
这个我以为没啥好说的了,注释写的很清楚了。。。
这只是中间过程当中的一个版本,虽而后来被抛弃了。。。可是还有有点意义的。。
就是遍历时间太长了。。。