记录一次FTP下载文件时ftpClient.listFiles(path)时size为0的解决方法

在Linux系统下使用FTP下载文件时遇到ftpClient.listFiles(path)返回size为0的问题,通过调试发现changeWorkingDirectory方法返回false。解决方法是确保传入的路径以'/'开头,并在路径正确时执行下一步,因为Linux对路径的处理比Windows更严格。

记录一次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;
    }

最后问题解决,希望能帮到同样问题的朋友,瑾以此记录自己失误的地方!

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值