public class ApacheFtpUtil { ???private Logger log = LoggerFactory.getLogger(ApacheFtpUtil.class); ???private String host; ???private String username; ???private String password; ???// 控制端口 ???private int port = 21; ???// 秒数 ???private int defaultTimeoutSecond = 60; ???private int connectTimeoutSecond = 30; ???private int dataTimeoutSecond = 30; ???// 秒 ???private int controlKeepAliveTimeout = 120; ???private boolean isTextMode = false; ???private String tranEncoding = "GB2312"; ???private FTPClient client; ???public ApacheFtpUtil(String host, String username, String password) { ???????this(host, username, password, 21, 0); ???} ???public ApacheFtpUtil(String host, String username, String password, int port) { ???????this(host, username, password, port, 0); ???} ???public ApacheFtpUtil(String host, String username, String password, int port, int security) { ???????this.host = host; ???????this.port = port; ???????this.username = username; ???????this.password = password; ???} ???public void initClint() throws Exception { ???????// FTPSClient ???????client = new FTPClient(); ???????// 每大约2分钟发一次noop,防止大文件传输导致的控制连接中断 ???????client.setControlKeepAliveTimeout(controlKeepAliveTimeout); ???????// client.setListHiddenFiles(listHiddenFiles); ???????// FTPClientConfig config = new ???????// FTPClientConfig(FTPClientConfig.SYST_NT); ???????// config.setServerLanguageCode("zh"); ???????// config.setUnparseableEntries(saveUnparseable); ???????// config.setDefaultDateFormatStr(defaultDateFormat); ???????// config.setRecentDateFormatStr(recentDateFormat); ???????// client.configure(config); ???????// 设置默认超时 ???????client.setDefaultTimeout(defaultTimeoutSecond * 1000); ???????// 连接超时 ???????// client.setConnectTimeout(connectTimeoutSecond * 1000); ???????// 设置数据超时 ???????// client.setDataTimeout(dataTimeoutSecond * 1000); ???????/* ????????* socket超时 设置一个命令执行后最大等待Server反馈的时间. 如果对方连接状态60秒没有收到数据的话强制断开客户端 ????????*/ ???????// client.setSoTimeout(60 * 1000); ???????// client.setBufferSize(1024); ???????// 连接到远程的FTP服务器. ???????try { ???????????client.connect(this.host, this.port); ???????} catch (Exception e) { ???????????this.destory(); ???????????log.error("连接服务器失败,host:{}, port:{}", this.host, this.port); ???????????throw e; ???????} ???????int reply = client.getReplyCode(); // 获得返回的代码,来判断连接状态 ???????if (!FTPReply.isPositiveCompletion(reply)) { ???????????this.destory(); ???????????// 连接错误 ???????????throw new Exception("Can‘t Connect to :" + host); ???????} ???????// 登录 ???????boolean flag = client.login(this.username, this.password); ???????if (flag == false) { ???????????this.destory(); ???????????throw new Exception("Invalid user/password"); ???????} ???????try { ???????????if (FTPReply.isPositiveCompletion(client.sendCommand("OPTS UTF8", "ON"))) { ???????????????// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码 ???????????????tranEncoding = "UTF-8"; ???????????????log.debug("FTP Server allow UTF8 encoding"); ???????????} ???????} catch (Exception e) { ???????????log.error("ftp server opts utf8 error,{}", e.getMessage()); ???????} ???????log.info("use encoding {}", tranEncoding); ???????client.setControlEncoding(tranEncoding); // 中文支持 ???????// 设置传送模式 ???????if (isTextMode) { ???????????client.setFileType(FTP.ASCII_FILE_TYPE); ???????} else { ???????????client.setFileType(FTP.BINARY_FILE_TYPE); ???????} ???????/* ????????* PORT中文称为主动模式,工作的原理: ????????* FTP客户端连接到FTP服务器的21端口,发送用户名和密码登录,登录成功后要list列表或者读取数据时, ????????* 客户端随机开放一个端口(1024以上),发送 PORT命令到FTP服务器,告诉服务器客户端采用主动模式并开放端口; ????????* FTP服务器收到PORT主动模式命令和端口号后,通过服务器的20端口和客户端开放的端口连接,发送数据. ????????* 主动模式需要客户端必须开放端口给服务器,很多客户端都是在防火墙内,开放端口给FTP服务器访问比较困难。 ????????*/ ???????// client.enterLocalActiveMode(); //主动模式 ???????/* ????????* PASV是Passive的缩写,中文成为被动模式. ????????* 工作原理:FTP客户端连接到FTP服务器的21端口,发送用户名和密码登录,登录成功后要list列表或者读取数据时, ????????* 发送PASV命令到FTP服务器, 服务器在本地随机开放一个端口(1024以上),然后把开放的端口告诉客户端, ????????* 客户端再连接到服务器开放的端口进行数据传输. 被动模式只需要服务器端开放端口给客户端连接就行了。 ????????*/ ???????client.enterLocalPassiveMode(); ???????// client.setUseEPSVwithIPv4(useEpsvWithIPv4); ???????log.debug("==========初始化FTP连接成功==========="); ???} ???public void destory() { ???????if (client == null) { ???????????return; ???????} ???????try { ???????????client.logout(); ???????} catch (IOException e) { ???????????e.printStackTrace(); ???????} ???????try { ???????????client.disconnect(); ???????} catch (IOException e) { ???????????e.printStackTrace(); ???????} ???????client = null; ???} ???public void changeRemoteDir(String newPath) throws RuntimeException { ???????// 切换路径[相对路径和绝对路径都可] ???????if (StringUtils.isBlank(newPath)) { ???????????return; ???????} ???????try { ???????????boolean flag = client.changeWorkingDirectory(new String(newPath.getBytes(tranEncoding), "ISO-8859-1")); ???????????log.debug("change working directory to {}, status:{}", newPath, flag); ???????} catch (IOException e) { ???????????throw new RuntimeException("切换路径失败:" + newPath + "; " + e.getMessage()); ???????} ???} ???/** ????* 下载文件 ????*/ ???public void download(String remoteFile, String localOutFile) throws RuntimeException { ???????FileOutputStream outstream = null; ???????// 下载文件 ???????try { ???????????log.debug("开始下载文件 {}", remoteFile); ???????????outstream = new FileOutputStream(new File(localOutFile)); ???????????/* ????????????* 这个方法的意思就是每次数据连接之前,ftp client告诉ftp server开通一个端口来传输数据. 因为ftp ????????????* server可能每次开启不同的端口来传输数据,但是在linux上,由于安全限制,可能某些端口没有开启,所以就出现阻塞 ????????????*/ ???????????client.enterLocalPassiveMode(); ???????????client.setFileType(FTP.BINARY_FILE_TYPE); ???????????/* ????????????* FTP协议里面,规定文件名编码为iso-8859-1,所以目录名或文件名需要转码 retrieveFile的第一个参数需要是 ????????????* ISO-8859-1 编码 ????????????*/ ???????????client.retrieveFile(new String(remoteFile.getBytes(tranEncoding), "ISO-8859-1"), outstream); ???????} catch (IOException e) { ???????????throw new RuntimeException("下载文件失败:" + remoteFile + "; " + e.getMessage()); ???????} finally { ???????????if (outstream != null) { ???????????????try { ???????????????????outstream.flush(); ???????????????????outstream.close(); ???????????????} catch (IOException e) { ???????????????} ???????????} ???????} ???????log.debug("下载文件 {} 完成", remoteFile); ???}}
使用commons-net来下载文件(仅做记录)
原文地址:http://blog.51cto.com/dengshuangfu/2130277