Spring 带有 RotatingServerAdvice 的 SFTP 适配器 InboundAdapter - 获取完整路径

Spring SFTP Adapter InboundAdapter with RotatingServerAdvice - Getting full path

使用 spring-integration-sftp: 5.1.3

我有一个 RotatingServerAdvice 的入站设置,它正在监视两个目录:

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

正在观看:inbox/dir1inbox/dir2

本地目录:temp/sftp

当我将文件放入 inbox/dir1/file1.txt 时,我的处理程序按预期被调用并且 file1.txt 被复制到 temp/sftp/file1.txt(<- 这就是问题所在,详情如下)

问题:

我的用例是,当我获取文件时,我想知道它来自哪个远程子目录。如果本地文件被传输到 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

像这样的东西应该有用...

继承 StandardRotationPolicy,重写

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

       ...

    }

调用 super.beforeReceive(source) 然后将源转换为 AbstractInboundFileSynchronizingMessageSource<?>

然后调用getCurrent()得到当前的KeyDirectory

然后abstractInboundFileSynchronizingMessageSource.setLocalDirectory(new File(...));

将您的自定义实现添加到建议中。

但是,您必须在消息源中使用 RecursiveDirectoryScanner,以便扫描树。

或者,使用配置为每次使用备用目录的 MGET 命令的出站网关(或者只是 inbox 在递归模式下)。网关可以配置为重新创建远程树。

由于我是新手,因此在实施建议的解决方案时遇到了一些麻烦。我采用了不同的方法,因为它可以很好地满足我的要求:

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. 远程目录上的自定义逻辑
  3. 删除确认文件

让这变得不那么棘手的一件事是了解本地文件处理程序中的远程目录(可能在 headers 中),但我没有找到找到它的方法。