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



我需要在Sftp服务器中复制/复制远程文件,复制时也要重命名,我在这里读到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:UsersDELLDesktopGetTestSpring Integration.txt
2021-02-16 18:10:22,784 INFO  [http-nio-9090-exec-1] org.springframework.core.log.LogAccessor: GenericMessage [payload=C:UsersDELLDesktopGetTestSpring 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, 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=1bf83b0f-3b24-66bd-ffbf-2a9018b499fb, sourcePath=/uploads, file_remoteFile=Spring Integration.txt, 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) {
}

此代码位于ChannelSftp.class_put方法中

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

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版本吗?

我认为我们可以改进警告消息,如果不调用exists(),就不要调用File.delete()

请随意提供这样的贡献!

演示如何在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();
}

最新更新