帮同事查看ftp上传文件失败的问题,发现了以上报错。

排查文件路径是否有授权

  查看了linux中的文件目录,查看是否为权限问题(如有问题,可执行:chmod -R 777 文件夹名)。
  使用debug查看sendCommand方法返回的replycode为250,也表明文件夹创建成功。

查看是否是切换文件夹路径时报错

  切换文件夹路径方法名为:changeWorkingDirectory。通过idea debug模式的evaluate查看ftp的当前路径:printWorkingDirectory,发现result为null!!!ftp是根据当前路径一层层去切换路径的,初始路径为null肯定会导致失败。
  初始化ftp时,是给ftp初始化了路径的,为什么此时当前路径为null呢?后查看发现同事是先从ftp获取了文件(调用了方法:retrieveFileStream),然后再执行文件上传。在从ftp上传文件夹前,printWorkingDirectory打印的目录是有值的,执行完retrieveFileStream方法后,再调用printWorkingDirectory方法,返回结果就为null了。

解决方案

  为什么会变成null,原因不清楚。现有解决方案是,执行retrieveFileStream方法并将流关闭后,要执行completePendingCommand方法,这时,printWorkingDirectory方法又能正常返回当前文件路径了。

    public ByteArrayOutputStream downloadStream(String ftpPath, String fileName) throws IOException {
        if (!setReady()) {
            throw new RuntimeException("ftp 连接失败");
        }
        // 切换到文件目录下,并获取目录下所有文件
        client.changeWorkingDirectory(ftpPath);
        FTPFile[] ftpFiles = client.listFiles(ftpPath);
        // 判断文件是否存在
        Boolean have = false;
        int size = 0;
        for (FTPFile ftpFile : ftpFiles) {
            if(StringUtil.equals(ftpFile.getName(),fileName)){
                // 避免编码问题,将匹配的文件名称赋值给 fileName
                fileName = ftpFile.getName();
                size = (int) ftpFile.getSize();
                have = true;
            }
        }
        // 判断文件是否存在
        if(!have){
            throw new RuntimeException("未查找到该文件");
        }

        // 建立传输连接,并读取文件 InputStream
        client.enterLocalPassiveMode();
        InputStream in = client.retrieveFileStream(new String(fileName.getBytes(config.getLocalEncoding()), config.getRemoteEncoding()));
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] b = new byte[(int) size];
        int len = 0;
        while ((len = in.read(b)) != -1) {
            out.write(b, 0, len);
        }
        out.flush();
        in.close();
        client.completePendingCommand();
        return out;
    }
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐