我试图使用Spring Integration实现以下场景:
@Component
public class SftpClient {
private static final Logger LOG = LoggerFactory.getLogger(SftpClient.class);
@Bean
public IntegrationFlow sftpInboundFlow() {
return IntegrationFlows
.from(Sftp.inboundAdapter(sftpSessionFactory())
.preserveTimestamp(true)
.remoteDirectory("data")
.regexFilter(".*\\.txt$")
// .localFilenameExpression("#this.toUpperCase() + '.a'")
.localDirectory(new File("ftp-inbound")),
e -> e.id("sftpInboundAdapter")
.autoStartup(true)
.poller(Pollers.fixedDelay(5000)))
.handle(m -> System.out.println(m.getPayload()))
.get();
}
@Bean
public IntegrationFlow sftpOutboundFlow() {
return IntegrationFlows.from("toSftpChannel")
.handle(Sftp.outboundAdapter(sftpSessionFactory(), FileExistsMode.FAIL)
.useTemporaryFileName(false)
.remoteDirectory("/data")
).get();
}
@Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
// // with private key resource: catch MalformedURLException
// try {
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost("myHost");
factory.setPort(22);
factory.setUser("myUser");
factory.setPassword("myPassword");
// factory.setPrivateKey(new FileUrlResource("/Users/myUser/.ssh/id_rsa"));
// factory.setPrivateKeyPassphrase("passphrase");
factory.setAllowUnknownKeys(true);
return new CachingSessionFactory<LsEntry>(factory);
// }
// catch (MalformedURLException e) {
// throw new IllegalArgumentException("malformed URL");
// }
}
在接受了Gary的建议后,我做了一个愚蠢的动态bean:
@Component
public class DynamicSftpTemplate implements InputStreamCallback {
private static Logger LOG = LoggerFactory.getLogger(DynamicSftpTemplate.class);
private String localDir;
private String localFilename;
public void getSftpFile(String sessionId, String host, int port, String user, String password,
String remoteDir, String remoteFilename, String localDir, String localFilename) {
LOG.debug("getSftpFile sessionId={}", sessionId);
ioSftpFile(GET, host, port, user, password,
remoteDir, remoteFilename, localDir, localFilename);
}
public void putSftpFile(String sessionId, String host, int port, String user, String password,
String remoteDir, String remoteFilename, String localDir, String localFilename) {
LOG.debug("putSftpFile sessionId={}", sessionId);
ioSftpFile(PUT, host, port, user, password,
remoteDir, remoteFilename, localDir, localFilename);
}
public void rmSftpFile(String sessionId, String host, int port, String user, String password,
String remoteDir, String remoteFilename) {
LOG.debug("rmSftpFile sessionId={}", sessionId);
ioSftpFile(RM, host, port, user, password, remoteDir, remoteFilename, null, null);
}
private void ioSftpFile(SftpOperationType op, String host, int port, String user, String password,
String remoteDir, String remoteFilename, String localDir, String localFilename) {
LOG.debug("ioSftpFile op={}, host={}, port={}", op, host, port);
LOG.debug("ioSftpFile user={}, password={}", user, password);
SftpRemoteFileTemplate template = new SftpRemoteFileTemplate(sftpSessionFactory(host, port, user, password));
template.setFileNameExpression(new LiteralExpression(remoteDir + "/" + remoteFilename));
template.setRemoteDirectoryExpression(new LiteralExpression(remoteDir));
//template.afterPropertiesSet();
this.localDir = localDir;
this.localFilename = localFilename;
if (op == GET) {
// template.get(buildGetMessage(remoteDir, remoteFilename), (InputStreamCallback) this);
template.get(remoteDir + "/" + remoteFilename, this);
}
else if (op == PUT) {
template.send(buildPutMessage(remoteDir, remoteFilename), FileExistsMode.REPLACE);
}
else if (op == RM) {
template.remove(remoteDir + "/" + remoteFilename);
}
else {
throw new IllegalArgumentException("invalid sftp operation, " + op);
}
}
private DefaultSftpSessionFactory sftpSessionFactory(String host, int port, String user, String password) {
LOG.debug("sftpSessionFactory");
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost(host);
factory.setPort(port);
factory.setUser(user);
factory.setPassword(password);
factory.setAllowUnknownKeys(true);
return factory;
}
private Message<?> buildPutMessage(String remoteDir, String remoteFilename) {
return MessageBuilder.withPayload(new File(this.localDir + "/" + this.localFilename))
.setHeader("file_remoteDirectory", remoteDir)
.setHeader("file_remoteFile", remoteFilename)
.build();
}
public void doWithInputStream(InputStream is) throws IOException {
LOG.debug("doWithInputStream");
String fullPathName = this.localDir + "/" + this.localFilename;
FileWriter w = new FileWriter(fullPathName);
IOUtils.copy(is, w, "UTF-8");
LOG.debug("doWithInputStream file {} written", fullPathName);
w.close();
is.close();
}
}
您可以使用SFTP网关来获取和放置文件(以及其他操作)。
或者,您可以直接使用SFTPremoteFileTemplate
。
如何通过注释而不是常规配置文件配置入站通道适配器?我可以为会话工厂定义bean,如下所示: 如何配置通过注释下给出的入站通道适配器? 我正在寻找的是在应用程序启动时连接所有bean,然后公开一些方法来开始轮询服务器,处理它们,然后从本地删除它们,类似于 其中getPollableChannel()为我提供了用于轮询的bean。
我发现了一个xml配置的入站适配器示例,但我并不完全理解。配置指定REST请求设置请求方法、使用的格式等。 我认为,从Spring集成的角度来看,响应应该更加重要,因为响应实际上是为消息通道提供信息的。我说得对吗? HTTP入站适配器用作消息endpoint(实际上是消息起始点),它调用HTTP请求,例如REST服务的URL。”http://myRest/transfer/next“-向SI消息通
我们正在使用spring integration sftp入站通道适配器,它每隔几秒钟轮询一次,并将zip文件下载到本地目录进行进一步处理。当有一个大文件,客户端仍在上载该文件,而这个入站适配器拾取了那个不完整的文件时,问题就开始了。我们使用AcceptAllFileFilter进行远程筛选,对于本地筛选,我们有自定义筛选。 有没有更好的方法来忽略或检查文件是否完全上传,然后拿起进行处理?
我刚刚将我们的Spring Boot项目从引导升级到v2.6.2,从Spring Cloud升级到2021.0.0。 现在,我的远程配置获取没有任何效果,应用程序也无法获取正确的属性文件 [main]INFO o. s. c. c. c. ConfigServiceProperty tySourceLocator-从服务器获取配置:http://localhost:8080 [main]WARN