Java使用FTP时碰到的坑--服务部署到linux时storeFile返回false

背景

正常情况下,我们都是把上传的文件保存到Java服务运行的服务器上。前段时间根据公司正式环境上的情况,必须要把文件做成跨服务器存储,经过考虑,最终采用FTP工具存储文件。
因为保存的文件并不是客户使用的文件,而是给运维人员使用的,所以这里并不需要考虑太多,直接写个简单的功能实现就好了。

正文

FTP服务站点怎么建,网上很多教程,不做赘述。本文只记录碰到的坑。
我是在window下开发,FTP服务端是window操作系统,开发阶段测试也在window下debug进行,正式环境下Java服务运行在linux上,采用docker部署。
在开发时一切正常,可是部署到服务器上,没有报出任何异常,但是ftp.storeFile()返回false。

依赖

查阅不少资料,很多人找不到jar包,甚至到网上求博主私信jar包,我不太理解为什么找不到,这里直接maven引入依赖就行了。

        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.6</version>
        </dependency>

实现代码

    /**
     * @param url       服务器IP地址
     * @param port      服务器端口
     * @param userName  用户登录名
     * @param password  用户登录密码
     * @param storePath 服务器文件存储路径
     * @param fileName  服务器文件存储名称
     * @param is        文件输入流
     * @return 			true上传成功    false上传失败
     */
    public static boolean storeFile(String url,
                                    int port,
                                    String userName,
                                    String password,
                                    String storePath,
                                    String fileName,
                                    InputStream is) {
        boolean result = false;
        FTPClient ftp = new FTPClient();
        try {
            ftp.connect(url, port);// 连接至服务器,端口默认为21时,可直接通过URL连接
            ftp.login(userName, password);// 登录服务器
            // 判断返回码是否合法
            if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
                ftp.disconnect();// 不合法时断开连接
                return result;// 结束程序
            }
            ftp.setControlEncoding("UTF-8"); // 中文转码
            ftp.enterLocalPassiveMode();// 被动模式
            ftp.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);//设置传输方式为流方式
            ftp.changeWorkingDirectory(storePath); // 设置文件操作目录
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);// 设置文件类型,二进制
            ftp.setBufferSize(3072); // 设置缓冲区大小
            fileName = new String(fileName.getBytes("GBK"), "iso-8859-1");//文件名中文报错问题
            result = ftp.storeFile(fileName, is);//上传文件
            is.close();
            ftp.logout();// 登出服务器
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != is) {
                    is.close();
                }
                if (ftp.isConnected()) {
                    ftp.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

重点在下面这两句:
ftp.enterLocalPassiveMode();// 被动模式
ftp.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);//设置传输方式为流方式

主动模式和被动模式

  1. PORT主动模式:ftp.enterLocalActiveMode();
    在这个模式下,客户端通过服务端的默认端口与服务端连接。在使用时客户端会随机开发一个端口发送PORT命令道服务端,告诉服务端客户端采用了主动模式和开放的端口。服务端收到客户端的PORT命令后,与客户端连接发送数据。
  2. PASV被动模式:ftp.enterLocalPassiveMode();
    在这个模式下,客户端发送的命令为PASV,此时是服务端开放端口给客户端连接,对于客户端而言是被动连接上服务端(客户端:我很被动,因为你服务端不告诉我端口,请问我要怎么连接?),开始数据传输。
    在正式环境里面,服务器的防火墙基本都是开的,需要什么端口在开放什么端口,如果没有设置被动模式传输数据,那客户端恐怕一辈子都连不上服务端,这导致的结果就是文件传输请求成功了,但是文件没有传过去,返回false。
    这也就是为什么服务器上没有上传的文件了。
    至于为什么不会报错,我跟了一下源码,大概意思就是针对文件传输结果一个返回码的问题。
    在这里插入图片描述
    看上图,返回结果就是true或者false,并无报错。上面的注释大概意思就是请求会返回一个响应码,2开头为true,3开头就是false。
    最后附上调用方法:
			MultipartFile file = ((MultipartHttpServletRequest) request).getFile("file");
            if (!file.isEmpty()) {
                try {
                    InputStream inputStream = file.getInputStream();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                boolean res = FTPUtils.storeFile("127.0.0.1", "21", userName, password, "//", file.getOriginalFilename(), inputStream);
                if (!res) {
                    msg = "FTP发生异常---->>>>文件上传失败";
                    return new ResponseDto<>(RespCode.ERROR.getId(), msg, null);
                }

本文END。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值