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

时间:2016-07-13 13:13:56

标签: java ftp ftp-client ftp-server passive-mode

我正在使用带有JAVA的FTP传输文件。 我正在使用Apache的 FTPClient FTPServer 。但在特定环境中,有时文件不会被传输。我在 login 方法调用之前从 FTPClient 调用 enterLocalPassiveMode 方法,但有时文件不会被传输。

  1. storeFile 方法返回“false”。
  2. getReplyString 方法返回“200 Command TYPE okay”。
  3. list方法返回“227”。
  4. 成功传输文件后:

    1. list 方法返回150。
    2. getReplyString 方法返回“150文件状态正常;即将打开数据连接”。
    3. 客户代码:

              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 类中的 setPassivePorts 方法在服务器端设置被动端口范围,但问题仍然存在。

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

      提前致谢。

1 个答案:

答案 0 :(得分:0)

  

这是防火墙问题吗?

在这些情况下,正确的方法是关闭防火墙以测试或设置应用程序可以连接的一系列端口。但在生产环境中,这不是一种选择。因此,我唯一知道的是,在开发环境中工作正常并且在生产环境中出现问题。我的假设是防火墙阻塞了端口。

  

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

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

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

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

  1. 如果未使用被动模式,FTPClient中的getPassivePort()方法将返回-1。
  2. 在问题中,我提到FTPClient中的list()方法返回227代码。此代码还表明正在使用被动模式。我认为这段代码是错误的。真正发生的是进入被动模式后的错误,但是从上一个命令返回了代码。
  3. 设置本地端口无法解决问题。也许是因为我正在配置的本地端口仅用于命令通道。传输通道仍然在客户端使用随机端口。解决方案是尝试再次传输文件。如果传输失败,我断开客户端,然后我再次使用其他端口连接客户端,然后我尝试再次传输文件。在我的所有测试中,文件第二次成功传输。如果转移失败,我会尝试3次。

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