ftp下载文件一直崩

问题描述:我端写了个rest接口,对方发送文件地址到该端口,然后我端去下载文件,ftp协议。但是一段时间后,大概几个小时,对方服务器就会宕机。也就是搞崩了。

解决思路:一直怀疑是ftp连接未关闭、或者文件流未关闭导致的。

所以写了一下代码:

    public void download(ReqBody body) {

        FTPClient ftp = null;

        try {
            String vendor = body.getVendor();
            String localPath = config.getLocalpath() + "/" + vendor;
            File localDir = new File(localPath);
            if(!localDir.exists()){ //如果本地路径不存在,则创建
                localDir.mkdirs();
            }

            String connectionStr = body.getConnectionString().replaceAll("ftp://", "");
            String username = connectionStr.substring(0, connectionStr.indexOf(":"));
            String password = connectionStr.substring(connectionStr.indexOf(":") + 1, connectionStr.lastIndexOf("@"));
            String host = connectionStr.substring(connectionStr.lastIndexOf("@") + 1, connectionStr.lastIndexOf(":"));
            int port = Integer.parseInt(connectionStr.substring(connectionStr.lastIndexOf(":") + 1));

            String file = body.getFileList();
            ftp = new FTPClient();
            ftp.connect(host, port);
            ftp.login(username, password);
            ftp.enterLocalPassiveMode(); //默认是主动0 被动模式 ftp分布式采用
            ftp.setRemoteVerificationEnabled(false); //取消主机验证
            ftp.setControlEncoding("utf-8");
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);//二进制模式
            int reply = ftp.getReplyCode();

            if (FTPReply.isPositiveCompletion(reply)) {
                logger.info("连接FTP服务端成功!" + reply);
                File remoteFile = new File(file);
                File localFile = new File(localDir, remoteFile.getName());
                OutputStream os = new FileOutputStream(localFile);
                ftp.changeWorkingDirectory(remoteFile.getParent());
                logger.info("切换路径!" + remoteFile.getParent());
                boolean b = ftp.retrieveFile(remoteFile.getName(), os);
                if (b) {
                    logger.info("ftp文件下载成功:{}", file);
                } else {
                    logger.error("ftp文件下载失败:{}", file);
                }
                os.close();
            }else{
                logger.error("连接FTP服务端被拒绝!" + reply);
                return;
            }
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp != null) {
                try {
                    ftp.logout();
                    ftp.disconnect();
                    ftp = null;
                } catch (IOException e) {
                    logger.error("关闭FTP连接失败{}", e.getMessage());
                }
            }
        }
    }

可以看到代码里面:

io流都关闭了,ftp也登出断开连接了,但是还是崩

然后查了些资料,有这么一个方法:

ftpClient.completePendingCommand();

官方说法是:完成文件传输必须调用completependingcommand和检查它的返回值来验证成功。如果没有这样做,后续命令可能会意外地出错
简单来说:completePendingCommand()会一直在等FTP Server返回226 Transfer complete,但是FTP Server只有在接受到InputStream执行close方法时,才会返回。所以先要执行close方法
 

调用这个接口后,一定要手动close掉返回的InputStream,然后再调用completePendingCommand方法,若不是按照这个顺序,则会导致后面对FTPClient的操作都失败。

 然后我在文件流关闭后,执行这个方法,但是还是崩

于是我把ftpClient的logout和disconnect这段代码去掉。

不崩了。难道不能同时使用?


版权声明:本文为qqnbsp原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。