Ftp工具类编写中遇到的一些坑
一、commons-net的FTPClient,在使用public InputStream retrieveFileStream(String remote) 时第二次调用的时候获取到的文件流为null
在调用这个接口后,一定要手动close掉返回的InputStream,然后再调用completePendingCommand方法,若不是按照这个顺序。
则不对,伪代码:
- InputStream is = ftpClient.retrieveFileStream(remote);
- is.close();
- ftpClient.completePendingCommand();
在这里也可以类似使用ftpClient.getReply();方法
或者可以使用下列方法来替换上述使用方式
使用一个中间文件来做一个转接,这种方式比上述方法的好处就是自己容易控制,不容易出问题。伪代码如下:
- File localFile = new File(localPath, localFileName);
- OutputStream output = new FileOutputStream(localFile);
- ftpClient.retrieveFile(remoteFileName, output);
- output.close();
- InputStream input = new FileInputStream(localFile);
二、当使用ftp连接池做zip打包下载时,多文件下载时,使用retrieveFileStream()方法获取文件流的时候,只能获取到第一个文件,第二个文件为null。
同上面的方法一样。
PS:一二问题的解决方案,不是很确定。看到懂的请留言指教12
三、Windows和Linux环境下的差异
这里指的是ftp服务器部署在Linux和Windows下的差异。
/**
* 释放ftpClient
*
* @param ftpClient 使用的ftpClient
*/
private void releaseFtpClient(FTPClient ftpClient) {
if (ftpClient == null) {
return;
}
try {
boolean flag = true;
if (StringUtils.isEmpty(ftpOptionProperties.getFtpPath())) {
flag = this.changeWorkingDirectory("/", ftpClient);
} else {
flag = this.changeWorkingDirectory(ftpOptionProperties.getFtpPath(), ftpClient);
}
if (!flag) {
ftpClient.disconnect();
log.info("将FtpClient放回到pool中时,重置FtpClient所在文件夹失败");
} else {
ftpClientPool.returnObject(ftpClient);
}
} catch (Exception e) {
log.error("Could not return ftpClient to the pool", e);
// destroyFtpClient
try {
ftpClient.disconnect();
} catch (IOException ioe) {
log.error("Could not disconnect ftpClient");
}
}
}
上面的代码中,当用完ftpClient之后,将ftpClient放回pool的时候,需要将ftpClient的路径设置回ftp服务器的根路径。
在Windows环境下,使用this.changeWorkingDirectory("/", ftpClient);可以切换到/目录,但是在Linux环境下无法切换。需要通过切换指定目录的方式this.changeWorkingDirectory("/home/ftpfile", ftpClient);