java 实现 FTP 下载,解决假死问题
(1)在请求 FTP 服务进行下载文件时,需要循环遍历文件夹获取文件进行解析,但是在 in = ftpClient.retrieveFileStream(file.getName());
时,输入流总是获取到 null,一定要执行 in.close();关闭输出流之后,再执行 ftpClient.completePendingCommand();传输结束方法。
(2)FTP 服务使用的是 window 系统,在本地建了 window 虚拟机使用的是 window 开发,进行远程 ftp 访问是没有问题的数据能够解析并且入库,但是部署到 LINUX 系统后,在 retrieveFileStream 方法出现了线程阻塞,连接 ftp 服务的线程挂起。在 ftp 连接时,ftpClient.enterLocalPassiveMode(); 设置为被动传输模式就可以解决线程挂起问题。
(3)在使用 java,通过 FTP 下载文件,发现在下载过程中,程序出现假死的现象,就是既不报错,也不抛异常,还不终止,就是一直在跑服务,在这里分享下解决方案:
FTPClent 需要使用被动模式:
在调用 FTPClient.listFiles()或者 FTPClient.retrieveFile()方法前,调用 FTPClient.enterLocalPassiveMode()!
也就是说:“这个方法的意思就是每次数据连接之前,ftp client 告诉 ftp server 开通一个端口来传输数据。”
为什么要这样做呢,因为 FTPServer 可能每次开启不同的端口来传输数据,但是在 linux 上,由于安全限制,可能某些端口没有开启,所以就出现阻塞.
代码 1 如下:
//创建 FTP 连接
ftpClient.setDefaultPort(//FTP 端口号);
ftpClient.connect(//FTP 服务 IP 地址);
ftpClient.login(//FTP 用户名, //密码);
ftpClient.setBufferSize(1024);
//设置文件类型(二进制)
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
//每次数据连接之前,ftp client 告诉 ftp server 开通一个端口来传输数据
ftpClient.enterLocalPassiveMode();
//从 FTP 下载文件
boolean b = ftpClient.retrieveFile(//FTP 文件路径及文件名, //用以保存文件的文件输出流);
==========================华丽分割线==========================
代码 2 如下:
//ftp 指定目录下的 AEI 文件夹数组
FTPFile[] ftpDirectory = ftpClient.listFiles();
//循环遍历子文件夹下的所有文件
for(int i = 0;i < ftpDirectory.length;i++) {
//获取一个子文件夹
FTPFile oneDirectory = ftpDirectory[i];
//判断是否是文件夹
if(oneDirectory.isDirectory()){
//改变工作目录到指定目录的子文件夹
ftpClient.changeWorkingDirectory(oneDirectory.getName());
//获取子文件夹的所有报文
FTPFile[] files = ftpClient.listFiles();
//获取自目录下的报文
for(FTPFile file : files){
//D 报文获取
if("D".equals(file.getName().substring(0, 1))){
//获取输入流
in = ftpClient.retrieveFileStream(file.getName());
//根据文件名将对应输入流转换为字符流
br = new BufferedReader(new InputStreamReader(in));
//将文件名与文件内容的第一行赋予待解析报文 Map,防止 map 的 key 重复,将文件内容作为 key
filesMap.put(br.readLine(), file.getName());
//关闭输入流
in.close();
//ftp 传输结束
ftpClient.completePendingCommand();
//添加该文件到要删除源文件的报文集合
delFilesList.add("\\"+oneDirectory.getName()+"\\"+file.getName());
}
}
//将工作目录改回原指定目录,为了遍历下一个子文件夹
ftpClient.changeToParentDirectory();
}
}
//关闭 ftp 连接
ftpClient.disconnect();
//关闭字符缓冲输入流
if(br != null){
br.close();
}
版权声明: 本文为 InfoQ 作者【Steven】的原创文章。
原文链接:【http://xie.infoq.cn/article/16980810c04787c653edde0d2】。文章转载请联系作者。
评论