FTPClient上传文件内容为空/损坏/缺失

项目场景:

项目场景:本地项目联调OA系统的时候,在发送审批时会传送相关附件,该附件由本地项目上传至FTP,OA系统会根据我们提供的路径和文件名去FTP中找到该文件


问题描述:

同事写了一个FTPClient的工具类,侧重看一下连接部分的代码,主要出的问题也是在这一块内容上

public static boolean connect(FTPClient ftpClient,String host,String user,String password, String encoding){
        boolean flag = false;
        try {
            ftpClient.connect(host);
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.setControlEncoding(encoding);
            ftpClient.enterLocalPassiveMode();
            if (ftpClient.login(user,password)){
                flag = true;


                log.info("ftp connected");
            }
            else{
                log.info("ftp connect failed : user or password error");
                ftpClient.disconnect();
            }
        } catch (IOException e) {
            log.error("ftp connect failed , error {[]}",e);
            e.printStackTrace();
        }
        return flag;
    }

原因分析:

这段代码也是很多网上给出的代码,问题也就随之而来了,传txt文件完全没有问题,那么其它文件如图片、pdf等等的时候就会出现问题了。
做了很多测试,最后将问题定位在了ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
进入setFileType()方法,断点如下图位置在这里插入图片描述
程序运行后会发现并没有通过if判断,evaluate一下type(fileType)的值,会发现得到的值是530
然后我们继续进入isPositiveCompletion方法
在这里插入图片描述
那么530一定是不满足这个条件的,所以导致了我们的文件内容为空或损坏,FTPClient默认的传输格式是ASCII形式的
这里思考一下为什么是530返回,仔细看ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);的位置,是在connect以后,login以前,530在ftp中有未登录的意思
这样子问题就很明显了,大家自己去打断点的时候会发现,一共会经历三个码值,530、200、230,第二个是不是200我也记不太清了,这篇文章是解决问题的后两天写


解决方案:

问题找到以后,解决的方法也很简单了,把代码的顺序换一下就可以了

public static boolean connect(FTPClient ftpClient,String host,String user,String password, String encoding){
        boolean flag = false;
        try {
            ftpClient.connect(host);
            
            if (ftpClient.login(user,password)){
                flag = true;
                ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
                ftpClient.setControlEncoding(encoding);
                ftpClient.enterLocalPassiveMode();

                log.info("ftp connected");
            }
            else{
                log.info("ftp connect failed : user or password error");
                ftpClient.disconnect();
            }
        } catch (IOException e) {
            log.error("ftp connect failed , error {[]}",e);
            e.printStackTrace();
        }
        return flag;
    }

不仔细看的话很难发现差别

ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.setControlEncoding(encoding);
ftpClient.enterLocalPassiveMode();

主要就是这三行代码的位置要在login后面才会生效
到此为止,问题解决了
说点题外话,看看这三行代码
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);这个就是用来配置文件传输形式的,默认ASCII,我们一般都是配置用二进制形式传送
ftpClient.setControlEncoding(encoding);这个是用来配置编码的,其实除了上面的传输形式没什么问题,这个我是有点不太明白的,为什么需要在登录后配置才有效,可能涉及到其它问题,猜测:FTPClient登录后会产生新的对象,这时候引用地址会改变,也就导致了登录前的配置无效
ftpClient.enterLocalPassiveMode();这行代码倒是没有太大的感受,留着和删掉暂时没有影响,网上说是被动和主动,不过我没有去深究,感兴趣可以自行学习

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用 Apache Commons Net 库的 Java FtpClient 上传文件的示例代码: ```java import java.io.File; import java.io.FileInputStream; import java.io.IOException; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; public class FtpClientDemo { public static void main(String[] args) { String server = "ftp.example.com"; int port = 21; String user = "username"; String password = "password"; String remotePath = "/remote/path/"; String localFilePath = "/local/path/file.txt"; FTPClient ftpClient = new FTPClient(); try { // 连接 FTP 服务器 ftpClient.connect(server, port); ftpClient.login(user, password); // 设置文件传输模式为二进制 ftpClient.setFileType(FTP.BINARY_FILE_TYPE); // 切换到指定的远程目录 ftpClient.changeWorkingDirectory(remotePath); // 上传文件 File localFile = new File(localFilePath); FileInputStream inputStream = new FileInputStream(localFile); boolean success = ftpClient.storeFile(localFile.getName(), inputStream); inputStream.close(); if (success) { System.out.println("文件上传成功!"); } // 登出 FTP 服务器 ftpClient.logout(); } catch (IOException e) { e.printStackTrace(); } finally { try { // 断开连接 ftpClient.disconnect(); } catch (IOException e) { e.printStackTrace(); } } } } ``` 在示例代码中,首先使用 `FTPClient` 类连接 FTP 服务器,然后设置传输模式为二进制,切换到指定的远程目录,并上传指定的本地文件。最后,记得登出 FTP 服务器并断开连接。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值