微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 Spring Integration 在 sftp 中复制远程文件

如何解决使用 Spring Integration 在 sftp 中复制远程文件

我需要在 Sftp 服务器中复制/复制远程文件,复制时也重命名,我读到 here 不支持在 Sftp 中复制远程文件,所以我唯一可用的选项是 GET 文件到本地,然后 PUT 再次到 Sftp 并删除本地文件,我已经成功实现了我的目标,但问题是有来自 org.springframework.core.log.LogAccessor: 的日志打印我没有想法来自哪里。

有助于复制远程文件代码

 @Bean
public IntegrationFlow copyRemoteFile() {
    return IntegrationFlows.from("integration.channel.copy")
            .handle(Sftp.outboundGateway(sftpSessionFactory(),AbstractRemoteFileOutboundGateway.Command.GET,"headers[" + copY_SOURCE_PATH.value + "]+'/'+" +
                            "headers[" + copY_SOURCE_FILENAME.value + "]")
                    .autocreateLocalDirectory(true)
                    .fileExistsMode(FileExistsMode.REPLACE)
                    .localDirectory(new File(localPath)))
            .log(LoggingHandler.Level.INFO,"SftpcopyService")
            .handle(Sftp.outboundGateway(sftpSessionFactory(),AbstractRemoteFileOutboundGateway.Command.PUT,"payload")
                    .remoteDirectoryExpression("headers[" + copY_DEST_PATH.value + "]")
                    .fileNameGenerator(n -> (String)n.getHeaders().get(copY_DEST_FILENAME.value))
                    .fileExistsMode(FileExistsMode.REPLACE))
            .log(LoggingHandler.Level.INFO,"SftpcopyService")
            .handle((p,h) -> {
                try {
                      return Files.deleteIfExists(
                            Paths.get(localPath + File.separator + h.get(copY_SOURCE_FILENAME.value)));
                } catch (IOException e) {
                    e.printstacktrace();
                    return false;
                }
            })
            .get();

这是日志。

2021-02-16 18:10:22,577 WARN  [http-nio-9090-exec-1] org.springframework.core.log.LogAccessor: Failed to delete C:\Users\DELL\Desktop\GetTest\Spring Integration.txt
2021-02-16 18:10:22,784 INFO  [http-nio-9090-exec-1] org.springframework.core.log.LogAccessor: Genericmessage [payload=C:\Users\DELL\Desktop\GetTest\Spring Integration.txt,headers={file_remoteHostPort=X.X.X.X:22,replyChannel=nullChannel,sourceFileName=Spring Integration.txt,file_remoteDirectory=/uploads/,destFileName=Spring Integrat.txt,destPath=uploads/dest,id=5105bdd1-8180-1185-3661-2ed708e07ab9,sourcePath=/uploads,file_remoteFile=Spring Integration.txt,timestamp=1613479222779}]
2021-02-16 18:10:23,011 INFO  [http-nio-9090-exec-1] org.springframework.core.log.LogAccessor: Genericmessage [payload=uploads/dest/Spring Integrat.txt,id=1bf83b0f-3b24-66bd-ffbf-2a9018b499fb,timestamp=1613479223011}]

更令人惊讶的是,它甚至在流程执行之前就出现得很早,尽管我最后处理了文件删除。我怎样才能摆脱这个日志消息?虽然它不会影响我的过程,但日志消息具有误导性

还有什么更好的方法可以将远程文件复制到 sftp 中的另一个路径

编辑

就像你建议的那样,我尝试了 SftpRemoteFileTemplate.execute() 方法来复制 sftp 中的文件,但是当调用 session.write(InputStream stream,String path) 方法时,方法控件永远不会返回它永远保持控制

我试过调试,执行到这里时控制丢失:

for(_ackcount = this.seq - startid; _ackcount > ackcount && this.checkStatus((int[])null,header); ++ackcount) {
            }

代码位于 _putChannelSftp.class 方法

这是我正在尝试的示例代码

 public boolean copy() {
   return remoteFileTemplate.execute(session -> {
        if (!session.exists("uploads/Spring Integration.txt")){
            return false;
        }
        if (!session.exists("uploads/dest")){
            session.mkdir("uploads/dest");
        }
        InputStream inputStream = session.readRaw("uploads/Spring Integration.txt");
        session.write(inputStream,"uploads/dest/spring.txt");
        session.finalizeRaw();
        return true;
    });
}

请您指出我在这里犯了什么错误

解决方法

与其通过本地文件副本编写整个流程,我建议您查看 SftpRemoteFileTemplate.execute(SessionCallback<F,T>) 的单个服务激活器。该回调中提供的 SftpSession 可用于 InputStream readRaw()write(InputStream inputStream,String destination)。最后你必须调用 finalizeRaw()

LogAccessor 问题不清楚。您使用什么 Spring Integration 版本?您是否覆盖 Spring Core 版本?

我认为我们可以改进那个 WARN 消息,如果它没有 File.delete(),就不要调用 exists()

请随意提供这样的贡献!

更新

演示如何在 SFTP 服务器上执行复制的 JUnit 测试:

@Test
public void testSftpCopy() throws Exception {
    this.template.execute(session -> {
        PipedInputStream in = new PipedInputStream();
        PipedOutputStream out = new PipedOutputStream(in);
        session.read("sftpSource/sftpSource2.txt",out);
        session.write(in,"sftpTarget/sftpTarget2.txt");
        return null;
    });

    Session<?> session = this.sessionFactory.getSession();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    FileCopyUtils.copy(session.readRaw("sftpTarget/sftpTarget2.txt"),baos);
    assertThat(session.finalizeRaw()).isTrue();
    assertThat(new String(baos.toByteArray())).isEqualTo("source2");

    baos = new ByteArrayOutputStream();
    FileCopyUtils.copy(session.readRaw("sftpSource/sftpSource2.txt"),baos);
    assertThat(session.finalizeRaw()).isTrue();
    assertThat(new String(baos.toByteArray())).isEqualTo("source2");

    session.close();
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?