Spring Integration:如何使用 IntegrationFlow 在 sftp 上动态创建子目录

Posted

技术标签:

【中文标题】Spring Integration:如何使用 IntegrationFlow 在 sftp 上动态创建子目录【英文标题】:Spring Integration: How to dynamically create subdir on sftp using IntegrationFlow 【发布时间】:2019-03-23 12:43:43 【问题描述】:

我有一个用例将文件传输到动态创建的某些子目录下的 sftp。 我使用自定义 SftpMessageHandler 方法和网关得到了这个工作。但是这种方法的问题是,它不会在成功上传后删除本地临时文件。 为了解决这个问题,现在我使用 IntegrationFlow 和表达式 Advice(如下所示),这确实删除了本地文件,但我不知道如何动态创建远程子目录。我阅读了远程目录表达式,但不确定如何使用/实现它。

有人解决了这个问题吗?任何帮助表示赞赏!

@Bean
public IntegrationFlow sftpOutboundFlow() 

    return IntegrationFlows.from("toSftpChannel")
              .handle(Sftp.outboundAdapter(this.sftpSessionFactory())
                      .remoteFileSeparator("/")
                      .useTemporaryFileName(false)
                      .remoteDirectory("/temp"), c -> c.advice(expressionAdvice(c)))
                                     .get();




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


@MessagingGateway
public interface UploadGateway 
    @Gateway(requestChannel = "toSftpChannel")
    void upload(File file);

【问题讨论】:

【参考方案1】:

Sftp.outboundAdapter() 具有以下远程目录选项:

/**
 * Specify a remote directory path.
 * @param remoteDirectory the remote directory path.
 * @return the current Spec
 */
public S remoteDirectory(String remoteDirectory) 


/**
 * Specify a remote directory path SpEL expression.
 * @param remoteDirectoryExpression the remote directory expression
 * @return the current Spec
 */
public S remoteDirectoryExpression(String remoteDirectoryExpression) 


/**
 * Specify a remote directory path @link Function.
 * @param remoteDirectoryFunction the remote directory @link Function
 * @param <P> the expected payload type.
 * @return the current Spec
 */
public <P> S remoteDirectory(Function<Message<P>, String> remoteDirectoryFunction) 

因此,如果故事是关于 动态 子目录,您可以选择 remoteDirectoryExpressionremoteDirectory(Function) 并针对应用程序上下文中的消息或某个 bean 计算目标路径。

例如:

.remoteDirectoryExpression("'rootDir/' + headers.subDir")

另外请记住,对于不存在的目录,您也需要配置 .autoCreateDirectory(true)

【讨论】:

感谢您的回复,但这似乎对我不起作用。这是我修改后的代码(如下)我现在接受标题中的整个路径。 remoteDirectoryExpression("headers.path") @MessagingGateway public interface LettersUploadGateway @Gateway(requestChannel = "toSftpChannel") void upload(@Payload File file, @Header("path") String path); 请展示一下你是如何做到这一点的 remoteDirectoryExpression("headers.path") @MessagingGateway public interface LettersUploadGateway @Gateway(requestChannel = "toSftpChannel") void upload(@Payload File file, @Header("path") String path); 好吧,那还不确定。它看起来对我来说是正确的。因此,当您在该网关上调用 upload() 时,您将构建一个具有适当远程路径值的 path 参数。什么不符合您的预期?另外,请注意 SO 上的 cmets 中的代码是如何不可读的。使用正确的代码格式编辑您的问题会更好。 .remoteDirectoryExpression("headers.path").autoCreateDirectory(true) 这按预期工作!!

以上是关于Spring Integration:如何使用 IntegrationFlow 在 sftp 上动态创建子目录的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Micrometer 获取 Spring Integration 队列中的消息数?

INTEGRATION TESTING WITH SPRING AND JUNIT

如何在 Spring Integration 中动态注册 Feed Inbound Adapter?

Spring Integration:如何使用 IntegrationFlow 在 sftp 上动态创建子目录

Spring Integration Java DSL:如何使用 channelMapping 方法路由到标题中名称的通道?

Spring Integration:如何一次处理多条消息?