4

我正在使用

  • Sprint 集成(文件、SFTP 等)4.3.6
  • 春季启动 1.4.3
  • Spring 集成 Java DSL 1.1.4

我正在尝试设置一个 SFTP 出站适配器,它允许我将文件移动到远程系统上的目录,并在我的本地系统中删除或重命名该文件。

因此,例如,我想将文件a.txt放在本地目录中,并将其 SFTP 发送到目录inbound中的远程服务器。传输完成后,我希望删除或重命名a.txt的本地副本。

我玩弄了几种方法。所以这里是我常用的 SessionFactory 进行测试。

protected SessionFactory<ChannelSftp.LsEntry> buildSftpSessionFactory() {
    DefaultSftpSessionFactory sessionFactory = new DefaultSftpSessionFactory();
    sessionFactory.setHost("localhost");
    sessionFactory.setUser("user");
    sessionFactory.setAllowUnknownKeys(true);
    sessionFactory.setPassword("pass");
    CachingSessionFactory<ChannelSftp.LsEntry> cachingSessionFactory = new CachingSessionFactory<>(sessionFactory, 1);
    return cachingSessionFactory;
}

这是一个转换器,我必须在消息中添加一些标题

@Override
public Message<File> transform(Message<File> source) {
    System.out.println("here is the thing : "+source);
    File file = (File)source.getPayload();
    Message<File> transformedMessage = MessageBuilder.withPayload(file)
            .copyHeaders(source.getHeaders())
            .setHeaderIfAbsent(FileHeaders.ORIGINAL_FILE, file)
            .setHeaderIfAbsent(FileHeaders.FILENAME, file.getName())
            .build();
    return transformedMessage;
}

然后我有一个集成流,它使用轮询器来监视本地目录并调用它:

@Bean
public IntegrationFlow pushTheFile(){
    return IntegrationFlows
            .from(s -> s.file(new File(DIR_TO_WATCH))
                            .patternFilter("*.txt").preventDuplicates(),
                    e -> e.poller(Pollers.fixedDelay(100)))
            .transform(outboundTransformer)
            .handle(Sftp.outboundAdapter(this.buildSftpSessionFactory())
                    .remoteFileSeparator("/")
                    .useTemporaryFileName(false)
                    .remoteDirectory("inbound/")
            )
            .get();
}

这工作正常,但会留下本地文件。关于如何在上传完成后删除本地文件的任何想法?我应该看看SftpOutboundGateway吗?

提前致谢!

Artem 的回答非常完美!这是一个快速示例,它在推送后删除本地文件。

@Bean
public IntegrationFlow pushTheFile(){
    return IntegrationFlows
            .from(s -> s.file(new File(DIR_TO_WATCH))
                            .patternFilter("*.txt").preventDuplicates(),
                    e -> e.poller(Pollers.fixedDelay(100)))
            .transform(outboundTransformer)
            .handle(Sftp.outboundAdapter(this.buildSftpSessionFactory())
                    .remoteFileSeparator("/")
                    .useTemporaryFileName(false)
                    .remoteDirectory("inbound/"), c -> c.advice(expressionAdvice(c))
            )
            .get();
}

@Bean
public Advice expressionAdvice(GenericEndpointSpec<FileTransferringMessageHandler<ChannelSftp.LsEntry>> c) {
    ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
    advice.setOnSuccessExpression("payload.delete()");
    advice.setOnFailureExpression("payload + ' failed to upload'");
    advice.setTrapException(true);
    return advice;
}
4

1 回答 1

1

为此,您可以使用多种方法。

所有这些都是基于您对Sftp.outboundAdapter().

  1. .publishSubscribeChannel()允许您将相同的消息发送给多个订阅者,当第二个订阅者收到它时,只有第一个完成它的工作。默认情况下,如果您不指定Executor

  2. routeToRecipients()允许您通过不同的组件获得相同的结果。

  3. ExpressionEvaluatingRequestHandlerAdvice- 您将这个添加到.advice()端点Sftp.outboundAdapter()定义中 - 第二个.handle()参数并file.delete()通过以下方式执行onSuccessExpression

    .transform((Integer p) -> p * 2, c -> c.advice(this.expressionAdvice()))
    
于 2017-02-02T16:46:31.310 回答