使用commons-net对ftp文件上传下载


     项目中由于要使用到ftp服务,虽然之前对edtFTPj有研究,但是鉴于edtFTPj版本更新比较慢等原因,没有使用这个包,我们用的功能比较简单,先简单的介绍下。
     过程一般是先建立连接,登陆,然后执行命令,最后关闭连接,相对来说比较简单,直接上代码。
     需要说明的是,在写测试单元测试的时候,如果不依赖物理的ftp,就需要自己mock一个ftp了,我在网上找到一个mockFtpServer,具体用法大家可以参考。

package com.xxx.aaa.data.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.util.Calendar;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPReply;

import com.xxx.aaa.common.aaaConfig;
import com.xxx.aaa.common.exception.aaaBaseException;
import com.xxx.aaa.common.log.LoggerHelper;
import com.xxx.aaa.common.util.DateUtils;
import com.xxx.aaa.util.aaaConstants;

public class FtpClient {

	private final FtpClientConfig ftpConfig;
	private final FTPClient client;
	private boolean ready = false;

	public FtpClient(FtpClientConfig config) {
		ftpConfig = config;
		client = new FTPClient();
	}

	public void begin() throws aaaBaseException {
		try {
			if (connect() && login()) {
				setConfig();
				ready = true;
			}
		} catch (SocketException e) {
			LoggerHelper.err(this.getClass(), "Connect socket error!", e);
			throw new aaaBaseException("Connect socket error,reaseon:" + e.getMessage());
		} catch (IOException e) {
			LoggerHelper.err(this.getClass(), "Login server error!", e);
			throw new aaaBaseException("Login server error,reaseon:" + e.getMessage());
		}
	}

	private boolean connect() throws SocketException, IOException {
		client.connect(ftpConfig.getServer(), ftpConfig.getPort());
		int reply = client.getReplyCode();
		if (!FTPReply.isPositiveCompletion(reply)) {
			client.disconnect();
			LoggerHelper.info(this.getClass(), "Error connet server:{} on port:{}", ftpConfig.getServer(),
			        ftpConfig.getPort());
			return false;
		}
		return true;
	}

	private boolean login() throws IOException {
		boolean loginSuccess = client.login(ftpConfig.getUsername(), ftpConfig.getPassword());
		if (!loginSuccess) {
			client.logout();
			LoggerHelper.info(this.getClass(), "Error login username:{} with password:{}", ftpConfig.getUsername(),
			        ftpConfig.getPassword());
			return false;
		}
		return true;
	}

	/**
	 * ftp运行环境参数配置
	 * 
	 * @throws IOException
	 */
	private void setConfig() throws IOException {
		FTPClientConfig conf = new FTPClientConfig(ftpConfig.getFtpStyle());
		client.configure(conf);

		// 被动传输模式
		if (ftpConfig.getPassiveMode()) {
			client.enterLocalPassiveMode();
		}

		// 二进制传输模式
		if (ftpConfig.getBinaryFileType()) {
			client.setFileType(FTP.BINARY_FILE_TYPE);
		}

		// 设置当前工作目录
		client.changeWorkingDirectory(ftpConfig.getRootPath());
	}

	/**
	 * 下载文件
	 * 
	 * @param path
	 * @param name
	 * @return
	 * @throws UnsupportedEncodingException
	 * @throws IOException
	 */
	public String download(String fileName) throws aaaBaseException {
		if (!ready) {
			return "";
		}
		String localPath = aaaConfig.getTempDir();
		if (!localPath.endsWith("/")) {
			localPath = localPath + "/";
		}
		File file = null;
		FileOutputStream fos = null;
		String destFileName = generateDestFileName(fileName);
		try {
			file = new File(localPath + destFileName);
			FileUtils.forceMkdir(file.getParentFile());
			fos = new FileOutputStream(file);
			client.retrieveFile(fileName, fos);
			return destFileName;
		} catch (IOException e) {
			LoggerHelper.err(this.getClass(), "IO exception, fileName:{},reason:{}", destFileName, e.getMessage());
			throw new aaaBaseException(String.format("IO exception, fileName:%s,reason:%s", fileName, e.getMessage()));
		} finally {
			IOUtils.closeQuietly(fos);
			if (file != null) {
				file.setReadOnly();
			}
		}
	}

	private String generateDestFileName(String srcFileName) {
		Calendar now = Calendar.getInstance();
		String yyMMddHH = DateUtils.getDate2String(DateUtils.YYYYMMDD_HH, now.getTime());
		return yyMMddHH + "_" + srcFileName;
	}

	public String downloadWithMd5(String fileName, String... md5Name) throws aaaBaseException {
		String downFileFileName = download(fileName);

		String fileMd5Name = fileName + aaaConstants.MD5_EXTENSION;
		if (md5Name != null && md5Name.length > 0 && StringUtils.isNotBlank(md5Name[0])) {
			fileMd5Name = md5Name[0];
		}
		download(fileMd5Name);

		return downFileFileName;
	}
	
	public String downloadQuiet(String fileName, String... md5Name) throws aaaBaseException {
		begin();
		String downFileFileName = downloadWithMd5(fileName, md5Name);
		end();
		return downFileFileName;
	}

	/**
	 * 关闭连接
	 * 
	 * @throws aaaBaseException
	 */
	public void end() throws aaaBaseException {
		try {
			if (client.isConnected()) {
				client.logout();
			}
		} catch (IOException e) {
			LoggerHelper.err(this.getClass(), "Logout error!", e);
			throw new aaaBaseException("Logout error,reason:" + e.getMessage());
		} finally {
			if (client.isConnected()) {
				try {
					client.disconnect();
				} catch (IOException e) {
					LoggerHelper.err(this.getClass(), "Disconnect socket error!", e);
					throw new aaaBaseException("Disconnect socket error,reason:" + e.getMessage());
				}
			}
		}
	}

	/**
	 * 上传文件到ftp服务上去
	 * 
	 * @author wangye04
	 */
	public boolean upload(String filename) throws aaaBaseException {
		if (!ready) {
			throw new aaaBaseException("ftpClient isn't ready!");
		}
		String localPath = aaaConfig.getTempDir();
		if (!localPath.endsWith("/")) {
			localPath = localPath + "/";
		}
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(new File(localPath + filename));
			return client.storeFile(filename, fis);
		} catch (Exception e) {
			LoggerHelper.err(getClass(), "An exception happened, fileName:{},reason:{}", filename, e.getMessage());
			throw new aaaBaseException(e);
		} finally {
			IOUtils.closeQuietly(fis);
		}
	}
}


package com.xxx.aaa.data.ftp;

import org.apache.commons.net.ftp.FTPClientConfig;

import com.xxx.aaa.common.AAAConfig;

/**
 * ftp的配置类
 * 
 */
public class FtpClientConfig {

	/** ftp服务器地址 */
	private String server;

	/** ftp服务器端口 */
	private int port;

	/** ftp服务器用户名 */
	private String username;

	/** ftp服务器密码 */
	private String password;

	/** ftp服务器显示风格 一般为unix 或者nt */
	private String ftpStyle;

	/** 是否设置 passiveMode模式 */
	private boolean passiveMode;

	/** 是否设置以二进制传输文件 */
	private boolean binaryFileType;

	/** ftp服务器工作根目录 */
	private String rootPath;

	/** 单例,上游ftp服务 */
	private static FtpClientConfig sourceInstance = null;
	/** 单例 */
	private static FtpClientConfig targetInstance = null;

	/**
	 * 从联盟获取配置实例
	 * 
	 * @param file
	 * @return
	 */
	public static FtpClientConfig getSourceInstance() {
		if (null == sourceInstance) {
			sourceInstance = new FtpClientConfig();
			sourceInstance.initSourceConfig();
		}
		return sourceInstance;
	}

	/**
	 * 给下游系统提供服务
	 * 
	 * @return
	 */
	public static FtpClientConfig getTargetInstance() {
		if (null == targetInstance) {
			targetInstance = new FtpClientConfig();
			targetInstance.initTargetConfig();
		}
		return targetInstance;
	}

	/**
	 * 设置源ftp的属性
	 * 
	 * @throws Exception
	 */
	private void initSourceConfig() {
		setServer(AAAConfig.getConfigValueByKey("ftp.server"));
		setPort(Integer.parseInt(AAAConfig.getConfigValueByKey("ftp.port")));
		setUsername(AAAConfig.getConfigValueByKey("ftp.username"));
		setPassword(AAAConfig.getConfigValueByKey("ftp.password"));
		setFtpStyle(AAAConfig.getConfigValueByKey("ftp.ftpstyle"));
		setPassiveMode(AAAConfig.getConfigValueByKey("ftp.passivemode"));
		setBinaryFileType(AAAConfig.getConfigValueByKey("ftp.binaryfiletype"));
		setRootPath(AAAConfig.getConfigValueByKey("ftp.rootpath"));
	}

	/**
	 * 设置目标ftp的属性
	 * 
	 * @throws Exception
	 */
	private void initTargetConfig() {
		setServer(AAAConfig.getConfigValueByKey("ftp.target.server"));
		setPort(Integer.parseInt(AAAConfig.getConfigValueByKey("ftp.target.port")));
		setUsername(AAAConfig.getConfigValueByKey("ftp.target.username"));
		setPassword(AAAConfig.getConfigValueByKey("ftp.target.password"));
		setFtpStyle(AAAConfig.getConfigValueByKey("ftp.target.ftpstyle"));
		setPassiveMode(AAAConfig.getConfigValueByKey("ftp.target.passivemode"));
		setBinaryFileType(AAAConfig.getConfigValueByKey("ftp.target.binaryfiletype"));
		setRootPath(AAAConfig.getConfigValueByKey("ftp.target.rootpath"));
	}

	/**
	 * 读取二进制传输方式设置
	 * 
	 * @return
	 */
	public boolean getBinaryFileType() {
		return binaryFileType;
	}

	/**
	 * 默认以二进制形式传输文件
	 * 
	 * @param binaryFileType
	 */
	public void setBinaryFileType(String binaryFileType) {
		if (null == binaryFileType) {
			this.binaryFileType = true;
		} else {
			if ("".equals(binaryFileType.trim())) {
				this.binaryFileType = true;
			} else if ("true".equals(binaryFileType.trim())) {
				this.binaryFileType = true;
			} else if ("false".equals(binaryFileType.trim())) {
				this.binaryFileType = false;
			}
		}
	}

	public String getFtpStyle() {
		return ftpStyle;
	}

	/**
	 * 默认NT风格
	 * 
	 * @param style
	 */
	public void setFtpStyle(String style) {
		if (null == style) {
			this.ftpStyle = FTPClientConfig.SYST_NT;
		} else {
			if ("".equals(style.trim())) {
				this.ftpStyle = FTPClientConfig.SYST_NT;
			} else if ("unix".equals(style.trim())) {
				this.ftpStyle = FTPClientConfig.SYST_UNIX;
			} else if ("nt".equals(style.trim())) {
				this.ftpStyle = FTPClientConfig.SYST_NT;
			}
		}
	}

	public boolean getPassiveMode() {
		return passiveMode;
	}

	/**
	 * 默认支持passiveMode
	 * 
	 * @param passiveMode
	 */
	public void setPassiveMode(String passiveMode) {
		if (passiveMode == null) {
			this.passiveMode = true;
		} else {
			if ("".equals(passiveMode.trim())) {
				this.passiveMode = true;
			} else if ("true".equals(passiveMode.trim())) {
				this.passiveMode = true;
			} else if ("false".equals(passiveMode.trim())) {
				this.passiveMode = false;
			}
		}
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public int getPort() {
		return port;
	}

	/**
	 * 默认端口为21
	 * 
	 * @param port
	 */
	public void setPort(Integer port) {
		if (null == port) {
			port = 21;
		}
		this.port = port;
	}

	public String getRootPath() {
		return rootPath;
	}

	/**
	 * 默认根目录为"/"
	 * 
	 * @param rootPath
	 */
	public void setRootPath(String rootPath) {
		if (null == rootPath) {
			rootPath = "/";
		} else {
			if ("".equals(rootPath.trim()))
				rootPath = "/";
		}
		this.rootPath = rootPath.trim();
	}

	public String getServer() {
		return server;
	}

	public void setServer(String server) {
		this.server = server;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}
}

你可能感兴趣的:(commons-net)