文档章节

用commons-net包写Ftp客户端下载(二)

猴子
 猴子
发布于 2011/10/20 17:38
字数 1552
阅读 882
收藏 1

上次写完了工具类,那么然后就是另一个工具类了。

1.也就是对ftp上文件的遍历。

这里我发现了一个问题,下载文件的时候,每次都得重新连接,也就是一次连接只能下载一个文件。

虽然到最后我也没发现到底为啥是这样,但是我自己的测试是的确这样的。

所有下载的思路我就设置成,第一次连接,遍历出所有FTP服务器上的文件,然后根据遍历之后的结果进行下载。

这里我又遇到问题了,我经过遍历需要得到什么结果,才能下载,首先文件名字吧。然后文件在ftp的相对路径。也就是工作空间

关于路径,由于在commons-net里面封装了ftp上文件类就是org.apache.commons.net.ftp.FTPFile

但是你会发现,这个类中没有方法得到路径,这就郁闷了,竟然没有任何方法能后看出来这个文件是什么路径。那怎么知道某个文件的工作空间在什么地方。于是只能遍历了。。。

(但是到最后大家会发现,我这里用的递归遍历,消耗的时间太长,如果ftp文件少没问题,然后数量大了,光遍历的时间就太长了。。。。。。。所以之后遍历被抛弃了,解决版本下此说)

首先我先建立了一个封装我自己的类,就是封装了FTP文件的信息包括名字和其所有的工作空间。

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;
	}

这个我觉得没啥好说的了,注释写的很清楚了。。。

这只是中间过程中的一个版本,虽然后来被抛弃了。。。但是还有有点意义的。。

就是遍历时间太长了。。。

© 著作权归作者所有

猴子

猴子

粉丝 10
博文 14
码字总数 15499
作品 0
青岛
项目经理
私信 提问
用commons-net包写Ftp客户端下载(三)

由于上次说了,如果客户端遍历FTP服务器的话,如果FTP上文件数量很大,那样的话,递归遍历的时间会超级长。。 (还没有说明。。我们这是EJB项目。。是FTP服务器上调用我的这个客户端进行下载...

猴子
2011/10/20
504
1
用commons-net包写Ftp客户端下载(一)

由于需要客户需求,需要把Ftp上的所有文件下载到本地,包括目录和文件。看到文件数量的时候我就哭了。。 几万个文件,晕死。这个地方我遇到的几个困难我会一一说明。 下载commons-net包我就不...

猴子
2011/10/20
4.4K
1
FTP断点续传卡死的问题。

用Apache Commons-Net包中的FtpClient做文件上传,从手机上传到服务器,手机使用WiFi连接,Server是Linux的vsftpd搭建的。 有以下特殊情况:上传文件到一半的时候,手动关掉WiFi致其上传失败...

摆渡者
2015/07/29
1K
0
使用apache的FTPServer搭建ftp服务器

一:启动ftp服务 1.下载Apache FtpServer 1.0.6 Release: http://mina.apache.org/downloads-ftpserver.html 2.解压后res/conf下找到user.properties (修改密码为admin默认是md5加密后的) ......

路叫兽
2016/08/11
416
0
Redis c/c++, java 客户端连接

Redis 介绍 redis 这个想必大家都了解,关于redis的安装参考这里,redis使用文档参见这里,英文文档。 Redis C客户端的使用方法 Redis的c客户端 Hiredis使用比较广泛,下面主要介绍下它。 1,...

gfsfg8545
2014/05/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

python学习10.04:Python list列表使用技巧及注意事项

前面章节介绍了很多关于 list 列表的操作函数,细心的读者可能会发现,有很多操作函数的功能非常相似。例如,增加元素功能的函数有 append() 和 extend(),删除元素功能的有 clear()、 remo...

太空堡垒185
9分钟前
1
0
新手插画学习的方法?教你如何自学?

插画学习的方法?教你如何自学? 从小喜欢画一些漫画头像随笔画,但是其实没有基础。个人偏好小清新手绘风的插画(如下图),每每看到都希望自己能画出这样的作品。 我其实很想说画这种美术功...

huihuajiaocheng
14分钟前
3
0
面试题

1、实现clone();

gtandsn
25分钟前
3
0
CentOS 7 部署 tesseract-ocr

官方地址 github yum-config-manager --add-repo https://download.opensuse.org/repositories/home:/Alexander_Pozdnyakov/CentOS_7/ 若提示 yum-config-manager: command not found 执行以......

阿白
26分钟前
2
0
JAVA比较器中comparator的使用

一个专用的比较器Comparator Comparator是一个专用的比较器,当一个不支持自比较或者自比较函数不能满足要求时,可写一个比较器来完成两个对象之间大小的比较。Comparator体现了一种策略模式...

daxiongdi
26分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部