最近公司做的项目需要在甲方机房做内外网交互,文件传输这块就落到我头上了,参照前辈的经验,用FTP通过网闸做了个文件传输。刚开始还顺风顺水,没想到读取FTP其中一个文件中的文件然后备份到了另一个文件中时遇到了坑,各种百度查阅,然并卵啊,没有一个能解决问题的,终于在十几次点击中发现了一篇真理文章。
public boolean bakFtpFiles(String bakPath,String ftpPath,String fileName) {
boolean flag = false;
FTPClient ftpClient = getFtpClient();
InputStream is = null;
try {
ftpClient.changeWorkingDirectory(ftpPath);
FTPFile[] ftpFiles = ftpClient.listFiles();
if (ftpFiles != null && ftpFiles.length > 0) {
for (FTPFile file : ftpFiles) {
if(fileName.equals(file.getName())){
is = ftpClient.retrieveFileStream(file.getName());
if(is != null){
ftpClient.completePendingCommand();
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
ftpClient.makeDirectory(bakPath);
ftpClient.changeWorkingDirectory(bakPath);
flag = ftpClient.storeFile(file.getName(), is);
is.close();
if(flag){
ftpClient.changeWorkingDirectory(ftpPath);
ftpClient.deleteFile(file.getName());
}
}
}
}
}
ftpClient.logout();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ftpClient.isConnected()) {
try {
ftpClient.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return flag;
}
需要注意的就是这两个地方 :
获取到FTP上某个文件的流
is = ftpClient.retrieveFileStream(file.getName());
重点
ftpClient.completePendingCommand();
completePendingCommand()会一直在等FTP Server返回226 Transfer complete,但是FTP Server只有在接受到InputStream执行close方法时,才会返回。所以要执行close方法 ,如果不加ftpClient.completePendingCommand();这句,输出的文件size就会为0,具体时什么原因也懒得去研究了,每天忙的跟狗似的,哪有空研究真理,都是拿来主义。