问题描述
网上不少的ftp工具类,未设置超时时间,和判断是否登录成功,会引发以下问题:
问题1:使用ftpUtil下载文件,导致程序一直阻塞
问题2:ftp密码不正确,代码也会正常往下处理
问题分析
通过 jstack 进程号 > /tmp/tmp.txt 将线程的堆栈日志 写入tmp.txt文件
查看到该线程一直处于RUNNABLE状态
进入ftpclinet.connect(host,prot)方法,发现注释:
用该 socket 与服务端创建连接,并设置一个指定的超时时间,如果超时时间是0,表示超时时间为无穷大, 创建连接这个过程会进入阻塞状态,直到连接创建成功,或者发生某个异常错误
解决方法
设置超时时间:
设置控制连接连接超时的时间
○ setConnectTimeout()
设置控制连接数据读取超时的时间
○ setDefaultTimeout()
设置数据传输连接的数据读取超时的时间
○ setDataTimeout()
判断是否登录成功:
ftpClient.login未true时,才是登录成功的!
public class FtpUtil {
private static Logger logger = LoggerFactory.getLogger(FtpUtil.class);
public FtpUtil() {
}
public static boolean download(String host, int port, String username, String password, String ftpFile, String localPath) {
FTPClient ftpClient = new FTPClient();
FileOutputStream fos = null;
boolean flag = false;
try {
if (!new File(localPath).getParentFile().exists()) {
new File(localPath).getParentFile().mkdirs();
}
ftpClient.setConnectTimeout(30 * 1000);
ftpClient.setDefaultTimeout(30 * 1000);
ftpClient.setDataTimeout(90 * 1000);
ftpClient.connect(host, port);
if (!ftpClient.login(username, password)) {
throw new RuntimeException("FTP客户端登录失败!ReplyCode:"+ ftpClient.getReplyCode());
}
ftpClient.enterLocalPassiveMode();
fos = new FileOutputStream(localPath);
ftpClient.setFileType(2);
ftpClient.retrieveFile(ftpFile, fos);
flag = true;
} catch (Exception var17) {
var17.printStackTrace();
flag = false;
throw new RuntimeException("FTP客户端出错!", var17);
} finally {
IOUtils.closeQuietly(fos);
try {
ftpClient.disconnect();
} catch (IOException var16) {
var16.printStackTrace();
throw new RuntimeException("关闭FTP连接发生异常!", var16);
}
}
return flag;
}
}
ReplyCode对应信息
最后附上ftpClient.getReplyCode()的返回值的对应信息:
110 重新启动标记应答。在这种情况下文本是确定的,它必须是:MARK yyyy=mmmm,其中yyyy是用户进程数据流标记,mmmm是服务器标记。
120 服务在nnn分钟内准备好
125 数据连接已打开,准备传送
150 文件状态良好,打开数据连接
200 命令成功
202 命令未实现
211 系统状态或系统帮助响应
212 目录状态
213 文件状态
214 帮助信息,信息仅对人类用户有用
215 名字系统类型
220 对新用户服务准备好
221 服务关闭控制连接,可以退出登录
225 数据连接打开,无传输正在进行
226 关闭数据连接,请求的文件操作成功
227 进入被动模式
230 用户登录
250 请求的文件操作完成
257 创建 "PATHNAME "
331 用户名正确,需要口令
332 登录时需要帐户信息
350 请求的文件操作需要进一步命令
421 不能提供服务,关闭控制连接
425 不能打开数据连接
426 关闭连接,中止传输
450 请求的文件操作未执行
451 中止请求的操作:有本地错误
452 未执行请求的操作:系统存储空间不足
500 格式错误,命令不可识别
501 参数语法错误
502 命令未实现
503 命令顺序错误
504 此参数下的命令功能未实现
530 未登录(用户名或密码错误,1、FTP密码修改了?2、用户名/密码输入错误?先仔细检查有无输入错误 如复制的时候误复制了空格!!)
532 存储文件需要帐户信息
550 未执行请求的操作
551 请求操作中止:页类型未知
552 请求的文件操作中止,存储分配溢出
553 未执行请求的操作:文件名不合法