Spring 与 SFTP 集成
Spring Integration with SFTP
我正在构建一个小微服务来从 SFTP 文件服务器访问文件。我决定使用 Spring Integration SFTP 来完成这项工作。我是 Spring 集成的新手,对它的工作原理感到困惑。
我的目标是获取 SFTP 服务器上目录中的文件列表,并将它们呈现给用户界面。从那里用户将 select 一个文件下载,我将使用文件名将文件从 SFTP 服务器流式传输到用户界面。
我正在使用以下有效的代码。
Entire class to handle SFTP with SSH
@Slf4j
@Configuration
public class SftpConfig {
@Value("${sftp.host}")
private String sftpHost;
@Value("${sftp.port:22}")
private int sftpPort;
@Value("${sftp.user}")
private String sftpUser;
@Value("${sftp.privateKey:#{null}}")
private Resource sftpPrivateKey;
@Value("${sftp.privateKeyPassphrase:}")
private String sftpPrivateKeyPassphrase;
@Value("${sftp.password:#{null}}")
private String sftpPasword;
@Value("${sftp.remote.directory:/}")
private String sftpRemoteDirectory;
@Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost(sftpHost);
factory.setPort(sftpPort);
factory.setUser(sftpUser);
if (sftpPrivateKey != null) {
factory.setPrivateKey(sftpPrivateKey);
factory.setPrivateKeyPassphrase(sftpPrivateKeyPassphrase);
} else {
factory.setPassword(sftpPasword);
}
factory.setAllowUnknownKeys(true);
return new CachingSessionFactory<>(factory);
}
@ServiceActivator(inputChannel = "ftpLS")
@Bean
public SftpOutboundGateway getFtpLS() {
SftpOutboundGateway gateway = new SftpOutboundGateway(sftpSessionFactory(), "ls", "'" + sftpRemoteDirectory + "' + payload");
gateway.setOption(AbstractRemoteFileOutboundGateway.Option.NAME_ONLY);
return gateway;
}
@ServiceActivator(inputChannel = "ftpGet")
@Bean
public SftpOutboundGateway getFtpGet() {
SftpOutboundGateway gateway = new SftpOutboundGateway(sftpSessionFactory(), "get", "'" + sftpRemoteDirectory + "' + payload");
gateway.setOption(AbstractRemoteFileOutboundGateway.Option.STREAM);
return gateway;
}
@MessagingGateway(defaultRequestChannel = "ftpLS")
public interface FtpLS {
List list(String directory);
}
@MessagingGateway(defaultRequestChannel = "ftpGet")
public interface FtpGet {
InputStream get(String fileName);
}
}
运行
@Bean
public ApplicationRunner runner(SftpConfig.FtpLS ftpLS, SftpConfig.FtpGet ftpGet) {
return args -> {
List<String> list = ftpLS.list("139");
System.out.println("Result:" + list);
InputStream is = ftpGet.get("139/" + list.get(0));
String theString = IOUtils.toString(is,"UTF-8");
System.out.println("Result:" + theString);
};
}
我的第一个问题是这种方法正确吗?
其次,我是否需要两个接口才能使用两个不同的 SftpOutboundGateway?
最后,在做FtsGet的时候有没有更好的方式传入动态目录名?现在我正在传递我正在将 139 与字符串中的基本目录连接起来并通过接口传递它。
is this the correct approach?
是的,方法是正确的。尽管我建议不要将 isSharedSession
用于网关,因为它可能会被不同的用户从不同的线程使用。
do I need two interfaces?
不,你真的可以有一个 @MessagingGateway
,但有几个方法用自己的 @Gateway
注释标记。
is there a better way to pass in a dynamic directory?
不,你的做法是正确的。没有像 working directory
这样的东西可以自动切换,就像我们在 FTP.
中可以做的那样
我正在构建一个小微服务来从 SFTP 文件服务器访问文件。我决定使用 Spring Integration SFTP 来完成这项工作。我是 Spring 集成的新手,对它的工作原理感到困惑。
我的目标是获取 SFTP 服务器上目录中的文件列表,并将它们呈现给用户界面。从那里用户将 select 一个文件下载,我将使用文件名将文件从 SFTP 服务器流式传输到用户界面。
我正在使用以下有效的代码。
Entire class to handle SFTP with SSH
@Slf4j
@Configuration
public class SftpConfig {
@Value("${sftp.host}")
private String sftpHost;
@Value("${sftp.port:22}")
private int sftpPort;
@Value("${sftp.user}")
private String sftpUser;
@Value("${sftp.privateKey:#{null}}")
private Resource sftpPrivateKey;
@Value("${sftp.privateKeyPassphrase:}")
private String sftpPrivateKeyPassphrase;
@Value("${sftp.password:#{null}}")
private String sftpPasword;
@Value("${sftp.remote.directory:/}")
private String sftpRemoteDirectory;
@Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost(sftpHost);
factory.setPort(sftpPort);
factory.setUser(sftpUser);
if (sftpPrivateKey != null) {
factory.setPrivateKey(sftpPrivateKey);
factory.setPrivateKeyPassphrase(sftpPrivateKeyPassphrase);
} else {
factory.setPassword(sftpPasword);
}
factory.setAllowUnknownKeys(true);
return new CachingSessionFactory<>(factory);
}
@ServiceActivator(inputChannel = "ftpLS")
@Bean
public SftpOutboundGateway getFtpLS() {
SftpOutboundGateway gateway = new SftpOutboundGateway(sftpSessionFactory(), "ls", "'" + sftpRemoteDirectory + "' + payload");
gateway.setOption(AbstractRemoteFileOutboundGateway.Option.NAME_ONLY);
return gateway;
}
@ServiceActivator(inputChannel = "ftpGet")
@Bean
public SftpOutboundGateway getFtpGet() {
SftpOutboundGateway gateway = new SftpOutboundGateway(sftpSessionFactory(), "get", "'" + sftpRemoteDirectory + "' + payload");
gateway.setOption(AbstractRemoteFileOutboundGateway.Option.STREAM);
return gateway;
}
@MessagingGateway(defaultRequestChannel = "ftpLS")
public interface FtpLS {
List list(String directory);
}
@MessagingGateway(defaultRequestChannel = "ftpGet")
public interface FtpGet {
InputStream get(String fileName);
}
}
运行
@Bean
public ApplicationRunner runner(SftpConfig.FtpLS ftpLS, SftpConfig.FtpGet ftpGet) {
return args -> {
List<String> list = ftpLS.list("139");
System.out.println("Result:" + list);
InputStream is = ftpGet.get("139/" + list.get(0));
String theString = IOUtils.toString(is,"UTF-8");
System.out.println("Result:" + theString);
};
}
我的第一个问题是这种方法正确吗?
其次,我是否需要两个接口才能使用两个不同的 SftpOutboundGateway?
最后,在做FtsGet的时候有没有更好的方式传入动态目录名?现在我正在传递我正在将 139 与字符串中的基本目录连接起来并通过接口传递它。
is this the correct approach?
是的,方法是正确的。尽管我建议不要将 isSharedSession
用于网关,因为它可能会被不同的用户从不同的线程使用。
do I need two interfaces?
不,你真的可以有一个 @MessagingGateway
,但有几个方法用自己的 @Gateway
注释标记。
is there a better way to pass in a dynamic directory?
不,你的做法是正确的。没有像 working directory
这样的东西可以自动切换,就像我们在 FTP.