使用 FTP Apache Java 实现传输文件的问题

Problems to transfer files using FTP Apache Java implementation

我正在使用 FTP 和 JAVA 传输文件。 我正在使用来自 Apache 的 FTPClientFTPServer。但在特定环境下,有时文件不会传输。我在 login 方法调用之前从 FTPClient 调用 enterLocalPassiveMode 方法,但有时文件未传输。

  1. storeFile 方法returns "false".
  2. getReplyString 方法returns“200 命令类型好”。
  3. 列表方法returns "227".

文件传输成功时:

  1. list方法returns150.
  2. getReplyString 方法returns“150 文件状态正常;即将打开数据连接”。

客户代码:

        this.getFtpClientUtil().connect(settingsService.getServer(), settingsService.getFtpServerCommandChannelPort());

        int reply = this.getFtpClientUtil().getReplyCode();

        if (!FTPReply.isPositiveCompletion(reply)) {
            logger.error("Fail to connect to FTP Server");
            this.getFtpClientUtil().disconnect();
            isConnect = false;
            return false;
        }

        logger.info("FTP Server connected successfully");
        this.getFtpClientUtil().enterLocalPassiveMode();
        isConnect = this.getFtpClientUtil().login(settingsService.getftpUsername(), settingsService.getftpPassword());

服务器代码:

        // Data Configuration
        this.dataConfigurationFactory = new DataConnectionConfigurationFactory();
        dataConfigurationFactory.setPassiveAddress(this.ipAddress);
        dataConfigurationFactory.setPassiveExternalAddress(this.ipAddress);
        dataConfigurationFactory.setPassivePorts(this.settingsService.getFtpServerTransferChannelPort());

        // Listener
        listenerFactory = new ListenerFactory();
        listenerFactory.setPort(this.settingsService.getFtpServerCommandChannelPort());
        listenerFactory.setDataConnectionConfiguration(dataConfigurationFactory.createDataConnectionConfiguration());

        // Desliga SSL
        listenerFactory.setImplicitSsl(false);

        // User
        PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
        UserManager um = userManagerFactory.createUserManager();

        this.serverFactory = new FtpServerFactory();
        serverFactory.addListener("default", listenerFactory.createListener());
        serverFactory.setUserManager(um);

        UserFactory userFactory = new UserFactory();
        userFactory.setName(this.settingsService.getftpUsername());
        userFactory.setPassword(this.settingsService.getftpPassword());
        userFactory.setMaxIdleTime(60);

        final String absolutePath = this.settingsService.getftpHomeDirectory();

        userFactory.setHomeDirectory(absolutePath);
        userFactory.setAuthorities(Arrays.asList((Authority) new WritePermission()));

        User user = userFactory.createUser();
        um.save(user);

        // Connection Config
        connectionConfigFactory = new ConnectionConfigFactory();
        connectionConfigFactory.setAnonymousLoginEnabled(false);
        connectionConfigFactory.setMaxLogins(100);
        serverFactory.setConnectionConfig(connectionConfigFactory.createConnectionConfig());

这是防火墙问题吗?

我尝试使用 DataConnectionConfigurationFactory class 中的 setPassivePorts 方法在服务器端设置被动端口范围,但是问题继续。

是否有任何形式可以在客户端设置端口范围? 如何检查连接是否真的使用被动模式?

提前致谢。

Is this a firewall problem?

在这些情况下,正确的方法是关闭防火墙以测试或设置应用程序可以连接的端口范围。但在生产环境中,这不是一个选项。所以,我唯一知道的是,在开发环境中工作正常,在生产环境中出现问题。我的假设是防火墙阻止了端口。

Is there any form to set port ranges on the Client side? How can I check if the connection is really using passive mode?

可以在 FTPClient 的 connect() 方法上设置本地端口:

this.getFtpClientUtil().connect(settingsService.getServer(), settingsService.getFtpServerCommandChannelPort(), 
                InetAddress.getLocalHost(), getLocalPort());

可以通过两种方式验证连接是否使用被动模式:

  1. 如果未使用被动模式,FTPClient 的 getPassivePort() 方法将 return -1。
  2. 在问题中,我提到 FTPClient 的 list() 方法 return 是 227 代码。此代码还表示正在使用被动模式。我认为这段代码是错误的。真正发生的是进入被动模式后的错误,但是return编辑了之前命令的代码。

设置本地端口未能解决问题。也许是因为我正在配置的本地端口仅用于命令通道。传输通道仍然使用客户端的随机端口。解决方案是尝试再次传输文件。如果传输失败,我会断开客户端,然后使用其他端口再次连接客户端,然后再次尝试传输文件。在我所有的测试中,文件在第二次传输成功。转账失败我试3次

再次连接客户端时,如果使用相同的端口,java可能会抛出"java.net.BindException: Address already in use"。即使在断开客户端连接后,端口仍会继续锁定片刻。在这种情况下,我会在尝试连接之前验证该端口是否可用,如果有必要,我会尝试在另一个端口连接客户端。