java使用apache.commons.net.ftp工具实现FTP文件上传下载
package org.xqlee.utils.ftp;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPFileFilter;
import org.apache.commons.net.ftp.FTPReply;

/**
 * 
 * 
 * <pre>
 * _________________________INFO_____________________________
 * | Description : [采用apache的工具包进行ftp传输|下载暂不支持AIX系统] 
 * | Encoding    : [UTF-8]
 * | Package     : [org.xqlee.utils.ftp]
 * | Project     : [utils]
 * | Author      : [LXQ]
 * | CreateDate  : [2016年5月2日上午11:12:52]
 * | Updater     : []
 * | UpdateDate  : []
 * | UpdateRemark: []
 * | Company     : [Shallink Electronic Information]
 * | Version     : [v 1.0]
 * | Libs        : [commons-net-3.3.jar]
 * __________________________________________________________
 * </pre>
 */
public class FTPUtil {
	/** FTP端口 **/
	private int port = 0;
	/** FTP主机名或者IP **/
	private String host = "";
	/** FTP用户名称 ***/
	private String userName = "";
	/** FTP用户密码 **/
	private String userPassword = "";
	/** 本地字符集编码 **/
	private String encoding = "utf-8";

	/**
	 * 调用前必须配置ftp链接参数
	 * 
	 * @param port
	 *            链接端口号
	 * @param host
	 *            链接主机名或者IP/域名
	 * @param userName
	 *            ftp用户名
	 * @param userPassword
	 *            ftp密码
	 * @param localEncoding
	 *            本地字符集编码(默认null将设置为utf-8)
	 */
	public void setConfig(int port, String host, String userName, String userPassword, String encoding) {
		this.port = port;
		this.host = host;
		this.userName = userName;
		this.userPassword = userPassword;
		if (null != encoding && !"".equals(encoding)) {
			this.encoding = encoding;
		}
	}

	public FTPClient connectFTPServer() throws SocketException, IOException {
		// 实例化一个ftp客户端
		FTPClient ftpClient = new FTPClient();
		// 连接服务器
		log("HOST:" + host + " Port:" + port);
		ftpClient.connect(host, port);
		boolean isLogin = ftpClient.login(userName, userPassword);
		if (!isLogin) {
			throw new IOException("Login Ftp Server Fail,Plase Check Port,Host,user,password is all Rigth?");
		} else {
			log("Login Ftp Server Success!");
		}
		log("FTP Server Type:[" + ftpClient.getSystemType() + "]");
		return ftpClient;
	}

	/**
	 * 向ftp写文件(数据)
	 * 
	 * @throws IOException
	 * @throws SocketException
	 */
	public void upload(String srcFile, String destFile) throws SocketException, IOException {
		// 替换源文件和目标文件中的反斜杠
		srcFile = srcFile.replaceAll("\\\\", "/");
		destFile = destFile.replaceAll("\\\\", "/");
		// 文件路径处理,以便支持中文
		srcFile = new String(srcFile.getBytes(encoding), "iso-8859-1");
		destFile = new String(destFile.getBytes(encoding), "iso-8859-1");
		FTPClient ftpClient = null;
		// 创建本机源文件
		File src = new File(srcFile);
		// 转换文件输入流
		FileInputStream fis = new FileInputStream(src);
		// 获取ftpClient实例
		ftpClient = connectFTPServer();
		// 远程目录
		String destPath = destFile.substring(0, destFile.lastIndexOf("/"));
		// 判断文件目录是否存在
		if (!ftpClient.changeWorkingDirectory(destPath)) {
			// 不存在创建
			ftpClient.makeDirectory(destPath);
		}
		// 指定写入的目录
		ftpClient.changeWorkingDirectory(destPath);
		// 写操作/采用二进制方式传输
		ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
		// 文件名
		String fn = new String(src.getName().getBytes(encoding), "iso-8859-1");
		// 文件全路径
		String ffn = destPath + fn;
		// 执行传输[参数1:新文件名称;参数2:本地文件的输入流][注意]文件路径最好使用全路径否则可能发生空文件情况
		boolean us = ftpClient.storeFile(ffn, fis);
		if (us) {
			log("File [" + ffn + "] Upload Success!");
		} else {
			throw new IOException("File [" + ffn + "] Upload Fail!");
		}
		// 关闭文件输入流/退出登录/断开连接
		fis.close();
		boolean b = ftpClient.logout();
		if (b) {
			log("Logout Ftp Server Success!");
		} else {
			log("Logout Ftp Server Fail!");
		}
		ftpClient.disconnect();

	}

	/**
	 * 上传文件到指定目录
	 * 
	 * @param files
	 *            待上传的文件数组
	 * @param targetPath
	 *            远程短文件路径
	 * @throws IOException
	 *             可能发生的异常
	 */
	public void upload(File files[], String targetPath) throws IOException {
		for (int i = 0; i < files.length; i++) {
			if (!files[i].exists()) {
				throw new IOException("File Not Found![" + files[i].getAbsolutePath() + "]");
			}
		}
		// 对上传目标路径进行两次编码,进行中文的支持
		targetPath = new String(targetPath.getBytes(encoding), "iso-8859-1");
		FTPClient ftpClient = null;
		// 获取ftpClient实例
		ftpClient = connectFTPServer();
		// 判断文件目录是否存在
		if (!ftpClient.changeWorkingDirectory(targetPath)) {
			// 不存在创建
			ftpClient.makeDirectory(targetPath);
		}
		// 指定写入的目录
		ftpClient.changeWorkingDirectory(targetPath);
		// 写操作/采用二进制方式传输
		ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
		// 循环写入文件
		BufferedInputStream bis = null;
		int count = 0;
		for (int i = 0; i < files.length; i++) {
			bis = new BufferedInputStream(new FileInputStream(files[i]));

			// 避免发生空文件,使用全路径上传
			String tn = files[i].getName() + ".tmp";
			tn = new String(tn.getBytes(encoding), "iso-8859-1");
			String tmpFileName = targetPath + tn;
			String fn = files[i].getName();
			fn = new String(fn.getBytes(encoding), "iso-8859-1");
			String fileName = targetPath + fn;

			// 1.先上传到临时文件
			boolean us = ftpClient.storeFile(tmpFileName, bis);
			if (us) {
				log("File [" + new String(tmpFileName.getBytes("iso-8859-1"), encoding) + "] Upload Success!");
			} else {
				log("File [" + new String(tmpFileName.getBytes("iso-8859-1"), encoding) + "] Upload Fail!");
			}
			// 2.更名为目标文件
			boolean rs = ftpClient.rename(tmpFileName, fileName);
			if (rs) {
				log("File [" + new String(fileName.getBytes("iso-8859-1"), encoding) + "] mv Success!");
				count++;
			} else {
				log("File [" + new String(fileName.getBytes("iso-8859-1"), encoding) + "] mv Fail!");
			}
		}
		log("File Total [" + files.length + "] Transfer Success[" + count + "]");
		// 关闭文件输入流/退出登录/断开连接
		if (bis != null) {
			bis.close();
		}
		boolean b = ftpClient.logout();
		if (b) {
			log("Logout Ftp Server Success!");
		} else {
			log("Logout Ftp Server Fail!");
		}
		ftpClient.disconnect();
	}

	/**
	 * 下载FTP服务器文件到本地路径
	 * 
	 * @param SRCPATH
	 *            FTP服务器文件路径
	 * @param DESTPATH
	 *            本地存放路径
	 * @param fileFilter
	 *            文件名称过滤,不使用填写NULL
	 * @throws IOException
	 *             下载过程中可能出现的IO异常
	 */
	public void download(String SRCPATH, String DESTPATH, FTPFileFilter fileFilter) throws IOException {
		download(SRCPATH, DESTPATH, false, false, null, fileFilter);
	}

	/**
	 * 下载FTP服务器文件到本地,可选择删除下载后的文件[需要用户权限]
	 * 
	 * @param SRCPATH
	 *            源文件路径地址
	 * @param DESTPATH
	 *            下载到本地的路径地址
	 * @param isDelSrc
	 *            是否删除源文件
	 * @param fileFilter
	 *            文件名称过滤,不使用填写NULL
	 * @throws IOException
	 *             下载过程中可能出现的异常
	 */
	public void download(String SRCPATH, String DESTPATH, boolean isDelSrc, FTPFileFilter fileFilter)
			throws IOException {
		download(SRCPATH, DESTPATH, isDelSrc, false, null, fileFilter);
	}

	/**
	 * 从FTP下载文件,并提供备份文件到另外一个目录[备份需要权限]
	 * 
	 * @param SRCPATH
	 *            原文件目录
	 * @param DESTPATH
	 *            目标文件目录
	 * @param isBackupTo
	 *            是否移动备份
	 * @param backupPath
	 *            备份目录
	 * @param fileFilter
	 *            文件名称过滤,不使用填写NULL
	 * @throws IOException
	 *             下载过程中可能出现的IO异常
	 */
	public void download(String SRCPATH, String DESTPATH, boolean isBackupTo, String backupPath,
			FTPFileFilter fileFilter) throws IOException {
		download(SRCPATH, DESTPATH, false, isBackupTo, backupPath, fileFilter);

	}

	/**
	 * FTP 下载文件
	 * 
	 * @param SRCPATH
	 *            源文件路径
	 * @param DESTPATH
	 *            下载到本地路径
	 * @param isDelSrc
	 *            下载后是否删除源文件
	 * @param isBackupTo
	 *            是否将下载后的文件移动备份到其他地方
	 * @param backupPath
	 *            [当备份为true时]备份移动的目录
	 * @throws IOException
	 */
	protected void download(String SRCPATH, String DESTPATH, boolean isDelSrc, boolean isBackupTo, String backupPath,
			FTPFileFilter fileFilter) throws IOException {
		// 替换路径中的反斜杠
		SRCPATH = SRCPATH.replace("\\\\", "/");
		DESTPATH = DESTPATH.replace("\\\\", "/");
		backupPath = backupPath.replace("\\\\", "/");
		// 路径处理以便支持中文
		SRCPATH = new String(SRCPATH.getBytes(encoding), "iso-8859-1");
		DESTPATH = new String(DESTPATH.getBytes(encoding), "iso-8859-1");
		backupPath = new String(backupPath.getBytes(encoding), "iso-8859-1");
		// 处理路径
		if (!SRCPATH.endsWith("/")) {
			SRCPATH = SRCPATH + "/";
		}
		if (DESTPATH.endsWith("/")) {
			DESTPATH = DESTPATH + "/";
		}
		if (backupPath.endsWith("/")) {
			backupPath = backupPath + "/";
		}
		// 链接ftp
		FTPClient ftp = connectFTPServer();
		// 判断是否登陆成功
		int reply;
		reply = ftp.getReplyCode();
		if (!FTPReply.isPositiveCompletion(reply)) {
			ftp.disconnect();
			throw new IOException("=======MISS LOGIN,CONNECT DISCONNECT...======");
		}
		// 判断文件目录是否存在
		if (!ftp.changeWorkingDirectory(SRCPATH)) {
			// 不存在创建
			ftp.makeDirectory(SRCPATH);
		}
		ftp.changeWorkingDirectory(SRCPATH);// 转移到FTP服务器目录
		// 遍历下载的目录
		FTPFile[] fs = null;
		if (null == fileFilter) {
			fs = ftp.listFiles();
		} else {
			fs = ftp.listFiles(SRCPATH, fileFilter);
		}

		for (FTPFile ff : fs) {
			if (ff.isFile()) {
				// 解决中文乱码问题,两次解码
				String fn = new String(ff.getName().getBytes(encoding), "iso-8859-1");
				// =======判断本地文件目录是否存在,不存在创建=======
				File localPath = new File(DESTPATH);
				if (!localPath.exists()) {
					localPath.mkdirs();
				} else {
					if (localPath.isFile()) {
						localPath.delete();
						localPath.mkdirs();
					}
				}
				// =======处理文件名=======
				String localFileName = DESTPATH + fn;
				File localFile = new File(localFileName);
				String tmpFileName = DESTPATH + fn + ".tmp";
				String srcFileName = SRCPATH + fn;
				// 写操作,将其写入到本地文件中
				File tempFile = new File(tmpFileName);
				BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tempFile));
				// 使用全路径,防止空文件
				ftp.retrieveFile(srcFileName, bos);
				bos.close();
				// 下载完成更名本地
				tempFile.renameTo(localFile);
				// =======下载完成后,后续操作=======
				// 判断是否备份
				if (isBackupTo) {
					// 判断备份目录是否存在,不存在创建
					if (!ftp.changeWorkingDirectory(backupPath)) {
						// 不存在创建
						ftp.makeDirectory(backupPath);
					}
					// 执行备份移动
					boolean bk = ftp.rename(SRCPATH + "/" + fn, backupPath + "/" + fn);
					if (bk) {
						log("Backup Ftp File to [" + new String((backupPath + fn).getBytes("iso-8859-1"), encoding)
								+ "]Success !");
					} else {
						log("Backup Ftp File to [" + new String((backupPath + fn).getBytes("iso-8859-1"), encoding)
								+ "]Fail !");
					}
				} else {
					// 判断是否删除下载后的源文件
					if (isDelSrc) {
						boolean del = ftp.deleteFile(SRCPATH + "/" + fn);
						if (del) {
							log("Delete Source File[" + new String((SRCPATH + fn).getBytes("iso-8859-1"), encoding)
									+ "] Success!");
						} else {
							log("Delete Source File[" + new String((SRCPATH + fn).getBytes("iso-8859-1"), encoding)
									+ "] Fail!");
						}
					}

				}
			} else {
				// 迭代处理文件目录
				String dn = new String(ff.getName().getBytes(encoding), "iso-8859-1");
				download(SRCPATH + dn, DESTPATH + dn, isDelSrc, isBackupTo, backupPath + dn, fileFilter);
			}
		}
		boolean b = ftp.logout();
		if (b) {
			log("Logout Ftp Server Success!");
		} else {
			log("Logout Ftp Server Fail!");
		}
		ftp.disconnect();
	}

	/**
	 * 日志打印处理
	 * 
	 * @param msg
	 *            信息
	 */
	public void log(String msg) {
		String time = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
		msg = time + " - " + msg;
		System.out.println(msg);
	}
}