Проблемы с передачей файлов с использованием FTP-реализации Apache Java

Я передаю файлы по FTP с JAVA. Я использую FTPClient и FTPServer от Apache. Но в определенной среде иногда файл не передается. Я вызываю метод enterLocalPassiveMode из FTPClient перед вызовом метода login, но иногда файлы не передаются.

  1. Метод storeFile возвращает «false».
  2. Метод getReplyString возвращает «200 Command TYPE okay».
  3. Метод списка возвращает «227».

Когда файл передан успешно:

  1. Метод list возвращает 150.
  2. Метод getReplyString возвращает «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());

Это проблема брандмауэра?

Я попытался установить диапазоны пассивных портов на стороне сервера с помощью метода setPassivePorts из класса DataConnectionConfigurationFactory, но проблема не исчезла.

Есть ли форма для установки диапазонов портов на стороне клиента? Как я могу проверить, действительно ли соединение использует пассивный режим?

Заранее спасибо.


person Fagner Fonseca    schedule 13.07.2016    source источник
comment
Отредактируйте свой пост и включите минимальный набор кода, который вызывает проблему.   -  person Mike    schedule 13.07.2016
comment
Вы также можете добавить -Djavax.net.debug = all в командную строку java, и это покажет вам сетевой трафик   -  person Mike    schedule 13.07.2016
comment
Пожалуйста, не искажайте свой код и свой вопрос.   -  person Hovercraft Full Of Eels    schedule 14.11.2017
comment
Собственно, проблема это надуманная. Я думаю, что код не имеет значения. Но ладно.   -  person Fagner Fonseca    schedule 14.11.2017


Ответы (1)


Это проблема брандмауэра?

В этих случаях правильным способом будет отключить брандмауэр для проверки или установить диапазон портов, к которым приложение может подключиться. Но в производственной среде это было не вариант. Итак, единственное, что я знаю, это то, что в среде разработки все работает нормально, а в производственной среде возникают проблемы. Я предполагаю, что брандмауэр блокирует порты.

Есть ли форма для установки диапазонов портов на стороне клиента? Как я могу проверить, действительно ли соединение использует пассивный режим?

Локальный порт можно установить в методе connect () из FTPClient:

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

Проверить, использует ли соединение пассивный режим, можно двумя способами:

  1. Метод getPassivePort () из FTPClient вернет -1, если пассивный режим не используется.
  2. В вопросе я упомянул, что метод list () из FTPClient возвращает код 227. Этот код также указывает на то, что используется пассивный режим. Я думал, что это ошибка. На самом деле произошла ошибка после входа в пассивный режим, но был возвращен код из предыдущей команды.

Установка локального порта не решила проблему. Возможно, потому что локальный порт, который я настраиваю, предназначен только для командного канала. Канал передачи по-прежнему использует случайные порты на стороне клиента. Решение пытается снова передать файл. Если передача не удалась, я отключаю клиента, затем снова подключаю его, используя другие порты, а затем снова пытаюсь передать файл. Во всех моих тестах файлы были успешно переданы во второй раз. Ставлю 3 попытки, если передача не удалась.

При повторном подключении клиента, если использовался тот же порт, java могла выдать «java.net.BindException: Address already in use». Даже после отключения клиента порт продолжает оставаться заблокированным в течение нескольких секунд. В этом случае я проверяю, доступен ли порт, прежде чем пытаться подключиться, при необходимости я пытаюсь подключить клиента к другому порту.

person Fagner Fonseca    schedule 27.07.2016