记录一次Linux系统下FTP下载文件时ftpClient.listFiles(path)时size为0的解决方法
最近一次项目做一个ftp服务器文件下载并导入数据库的功能,从其他大神博客处提供的ftp工具类开始处理(https://blog.youkuaiyun.com/wangmx1993328/article/details/82150290),本地windows系统搭建的ftp服务器下载导入一切正常,并可以同步更新ftp服务器文件,大神的工具类用起来真不错。开始测试linux下的ftp服务器时下载一直出现问题,在获取所有文件时结果一直为根目录下的一个子目录,因为是递归调用,最后结果取的目录是这样/download/download/download/...无限循环。
获取所有文件的方法
public static List<String> loopServerPath(FTPClient ftpClient, String remotePath, List<String> relativePathList) {
/**如果 FTP 连接已经关闭,或者连接无效,则直接返回*/
if (!ftpClient.isConnected() || !ftpClient.isAvailable()) {
System.out.println("ftp 连接已经关闭或者连接无效......");
return relativePathList;
}
try {
/**转移到FTP服务器根目录下的指定子目录
* 1)"/":表示用户的根目录,为空时表示不变更
* 2)参数必须是目录,当是文件时改变路径无效
* */
ftpClient.changeWorkingDirectory(remotePath);
/** listFiles:获取FtpClient连接的当前下的一级文件列表(包括子目录)
* 1)FTPFile[] ftpFiles = ftpClient.listFiles("/docs/info");
* 获取服务器指定目录下的子文件列表(包括子目录),以 FTP 登录用户的根目录为基准,与 FTPClient 当前连接目录无关
* 2)FTPFile[] ftpFiles = ftpClient.listFiles("/docs/info/springmvc.txt");
* 获取服务器指定文件,此时如果文件存在时,则 FTPFile[] 大小为 1,就是此文件
* */
FTPFile[] ftpFiles = ftpClient.listFiles();
if (ftpFiles != null && ftpFiles.length > 0) {
for (FTPFile ftpFile : ftpFiles) {
if (ftpFile.isFile()) {
String relativeRemotePath = remotePath + "\\" + ftpFile.getName();
relativePathList.add(relativeRemotePath);
} else {
loopServerPath(ftpClient, remotePath + "\\" + ftpFile.getName(), relativePathList);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return relativePathList;
}
发现运行在本地时ftpFiles的size不为0,同样的目录结构在linux ftp服务器上size为0,我的ftp目录结构:

网上找了n中方法,有的说中文日期格式不支持,需要更改源码,有的说在调用listFiles()之前添加ftpClient.enterLocalPassiveMode()并不能解决我的问题。
最后通过调试发现ftpClient.changeWorkingDirectory的访问值一直是false,本地确返回true,原来这个方法是切换到指定工作路径,是我传入的参数路径读取不到,返回了false。
为什么windows下返回true,linux返回false呢,windows下查找根路径传入"" 可以获取根路径,而linux下传入""获取不到,只能传入"/"才能获取根路径,并且windows下传入路径是"/download"或"\download"都能正确获取,但是linux下只能传入"/upload"才能获取,最后通过更改路径为"/"模式,问题解决,至于原因可能是linux的路径获取比较严格。最后更改代码如下,判断返回值为true才正确执行下一步。
public static List<String> loopServerPath(FTPClient ftpClient, String remotePath, List<String> relativePathList) {
/**如果 FTP 连接已经关闭,或者连接无效,则直接返回*/
if (!ftpClient.isConnected() || !ftpClient.isAvailable()) {
System.out.println("ftp 连接已经关闭或者连接无效......");
return relativePathList;
}
try {
boolean b = ftpClient.changeWorkingDirectory(StringUtils.isEmpty(remotePath)?"/":remotePath);
if(b){ //为false时为路径错误,不然会一直从根目录递归。 linux根目录必须为/不能为空 目录只能用/不能用\
ftpClient.enterLocalPassiveMode(); // Use passive mode as default
//ftpClient.configure(new FTPClientConfig("com.bwdz.yys.util.UnixFTPEntryParser"));
FTPFile[] ftpFiles = ftpClient.listFiles();
if (ftpFiles != null && ftpFiles.length > 0) {
for (FTPFile ftpFile : ftpFiles) {
if (ftpFile.isFile()) {
String relativeRemotePath = remotePath + "/" + ftpFile.getName();
relativePathList.add(relativeRemotePath);
} else if (ftpFile.isDirectory()){
loopServerPath(ftpClient, remotePath + "/" + ftpFile.getName(), relativePathList);
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return relativePathList;
}
最后问题解决,希望能帮到同样问题的朋友,瑾以此记录自己失误的地方!
在Linux系统下使用FTP下载文件时遇到ftpClient.listFiles(path)返回size为0的问题,通过调试发现changeWorkingDirectory方法返回false。解决方法是确保传入的路径以'/'开头,并在路径正确时执行下一步,因为Linux对路径的处理比Windows更严格。

3791





