Spring SFTP-адаптер InboundAdapter с RotatingServerAdvice - получение полного пути - PullRequest
1 голос
/ 11 февраля 2020

Использование spring -gration-sftp: 5.1.3

У меня есть входящая настройка с RotatingServerAdvice, которая просматривает два каталога:

--inbox
-----dir1
-----dir2

Просмотр : inbox/dir1 и inbox/dir2

Локальный каталог: temp/sftp

Когда я помещаю файл в inbox/dir1/file1.txt, мой обработчик вызывается, как и ожидалось, и file1.txt копируется в temp/sftp/file1.txt (<- это проблема, подробности ниже) </p>

Проблема:

Мой пример использования: когда я получаю файл, я хочу знать, какой удаленный подкаталог, это . Если локальный файл был перенесен в temp/sftp/inbox/dir1/file1.txt, я мог бы сказать, что он пришел из /inbox/dir1, и я могу выполнить некоторые операции с удаленным sftp в этом каталоге.

Почему файл передается ровно, а не в подкаталогах локального каталога? Любая помощь приветствуется.

Входящий адаптер:

@Bean
public IntegrationFlow sftpInboundsFlow(DelegatingSessionFactory<LsEntry> delegatingSessionFactory,
    SftpServiceActivator serviceActivator) throws JSchException {

    SftpConnection config = sftpConnectionConfig.getSftpConnectionConfig(delegatingSessionFactory);

    return IntegrationFlows
        .from(Sftp.inboundAdapter(delegatingSessionFactory)
                .preserveTimestamp(true)
                .autoCreateLocalDirectory(true)
                .preserveTimestamp(true)
                .remoteDirectory("*")
                .filter(new CopartFileFilter(Pattern.compile(".*")))
                .localDirectory(new File( System.getProperty("java.io.tmpdir") + "/" + config.getLocalDirectory())),
                e -> e.id("inboundSftpChannel")
                .autoStartup(true)
                .poller(Pollers
                    .fixedDelay(config.getPollerInterval())
                    .advice(advice(delegatingSessionFactory))
                    .maxMessagesPerPoll(1)))
        .handle(m -> serviceActivator.handleMessage(m))
        .get();
}

Информация о файле на обработчике:

file: file1.txt, parent: /var/folders/sd/5k6jwzgs2hj2q165b6x9pql55mp8t7/T/sftp, headers {file_originalFile=/var/folders/sd/5k6jwzgs2hj2q165b6x9pql55mp8t7/T/sftp/file1.txt, id=d2620539-ab0d-2590-9b51-f4dfb442a74a, file_name=file1.txt, file_relativePath=file1.txt, timestamp=1581371879819}

Попробуйте 1:

Я думаю, что это похоже на первый упомянутый подход.

.localFilenameExpression("#remoteDirectory + '/' + #this")

Правильно помещает файл в temp/sftp/inbox/dir1/file1.txt. Проблема в том, что сообщение, которое я получаю, предназначено для этого каталога:

temp/sftp/inbox

Не file1.txt

Ответы [ 2 ]

1 голос
/ 11 февраля 2020

Примерно так должно работать ...

Подкласс StandardRotationPolicy, переопределение

    @Override
    public void beforeReceive(MessageSource<?> source) {

       ...

    }

Вызов super.beforeReceive(source), затем приведение источника к AbstractInboundFileSynchronizingMessageSource<?>.

Затем позвоните getCurrent(), чтобы получить текущий KeyDirectory.

Затем abstractInboundFileSynchronizingMessageSource.setLocalDirectory(new File(...));

Добавьте свою собственную реализацию к совету.

Однако вы будете необходимо использовать RecursiveDirectoryScanner в источнике сообщений, чтобы дерево было сканировано.

В качестве альтернативы используйте исходящий шлюз, настроенный на использование команды MGET с использованием альтернативных каталогов каждый раз (или просто inbox в рекурсивном режиме ). Шлюз можно настроить для воссоздания удаленного дерева.

0 голосов
/ 12 февраля 2020

У меня были проблемы с реализацией предложенных решений, потому что я был новичком в этом. Я выбрал другой подход, потому что он отлично работал для моего требования:

В sftpInboundsFlow

.localFilenameExpression("#remoteDirectory.replaceAll('/', '-') + '_' + #this")

Это помещает файлы в плоскую структуру в локальный временный каталог.

 temp/sftp:
       inbox-dir1_file1.txt

Затем в обработчике:

  1. Извлечение удаленного каталога из имени файла:

    public String extractRemoteDir(File ackFile) {
        String fileName = ackFile.getName();
        return fileName.split("_")[0].replaceAll("-", "/");
    }
    
  2. Настраиваемый лог c в удаленном каталоге
  3. Удалить ackFile

Одна вещь, которая сделает это менее хакерской, это узнать удаленный каталог в локальном обработчике файлов (возможно, в заголовках), но Я не нашел способ найти это.

...