对于最新的稳定版本,请使用 Spring Integration 6.4.0! |
FTP 出站通道适配器
FTP 出站通道适配器依赖于连接到 FTP 服务器的实现,并为它在传入消息的有效负载中接收的每个文件启动 FTP 传输。
它还支持文件的多种表示形式,因此您不仅限于 -typed payloads。
FTP 出站通道适配器支持以下有效负载:MessageHandler
java.io.File
-
java.io.File
:实际文件对象 -
byte[]
:表示文件内容的字节数组 -
java.lang.String
:表示文件内容的文本 -
java.io.InputStream
:要传输到远程文件的数据流 -
org.springframework.core.io.Resource
:用于将数据传输到远程文件的资源
以下示例说明如何配置 :outbound-channel-adapter
<int-ftp:outbound-channel-adapter id="ftpOutbound"
channel="ftpChannel"
session-factory="ftpSessionFactory"
charset="UTF-8"
remote-file-separator="/"
auto-create-directory="true"
remote-directory-expression="headers['remote_dir']"
temporary-remote-directory-expression="headers['temp_remote_dir']"
filename-generator="fileNameGenerator"
use-temporary-filename="true"
chmod="600"
mode="REPLACE"/>
前面的配置显示了如何使用元素配置 FTP 出站通道适配器,同时还为各种属性提供值,例如(策略接口的实现)、对 a 的引用和其他属性。
您还可以查看一些属性示例,这些属性允许您使用 SPEL 配置设置,例如、 、 和 (前面的示例中所示的 SPEL 替代项)。
与任何允许使用 SPEL 的组件一样,可以通过“payload”和“headers”变量访问有效负载和消息 Headers。
请参阅 架构 有关可用属性的更多详细信息。outbound-channel-adapter
filename-generator
o.s.i.file.FileNameGenerator
session-factory
*expression
remote-directory-expression
temporary-remote-directory-expression
remote-filename-generator-expression
filename-generator
默认情况下,如果未指定文件名生成器,则 Spring Integration 使用 。 根据 中的标头(如果存在)的值确定文件名,或者,如果 Message 的有效负载已经是 ,则它使用该文件的原始名称。o.s.i.file.DefaultFileNameGenerator DefaultFileNameGenerator file_name MessageHeaders java.io.File |
定义某些值 (如 ) 可能取决于平台或 FTP 服务器。
例如,正如 forum.spring.io/showthread.php?p=333478&posted=1#post333478 上报告的那样,在某些平台上,必须在目录定义的末尾添加斜杠(例如,而不是 )。remote-directory remote-directory="/thing1/thing2/" remote-directory="/thing1/thing2" |
从版本 4.1 开始,您可以指定 when transfer the file.
默认情况下,现有文件将被覆盖。
模式由枚举定义,其中包括以下值:mode
FileExistsMode
-
REPLACE
(默认) -
REPLACE_IF_MODIFIED
-
APPEND
-
APPEND_NO_FLUSH
-
IGNORE
-
FAIL
IGNORE
,并且不要传输文件。 导致引发异常,同时静默忽略传输(尽管生成了日志条目)。FAIL
FAIL
IGNORE
DEBUG
版本 5.2 引入了该属性,您可以使用该属性在上传后更改远程文件权限。
您可以使用传统的 Unix 八进制格式(例如,仅允许文件所有者进行读写操作)。
使用 java 配置适配器时,可以使用 或 。
仅当您的 FTP 服务器支持该子命令时才适用。chmod
600
setChmodOctal("600")
setChmod(0600)
SITE CHMOD
避免部分写入的文件
处理文件传输时出现的常见问题之一是处理部分文件的可能性。 也就是说,文件可能在传输实际完成之前就出现在文件系统中。
为了解决这个问题, Spring 集成 FTP 适配器使用一种通用算法:文件以临时名称传输,然后在完全传输后重命名。
默认情况下,正在传输的每个文件都会在文件系统中显示一个附加后缀,默认情况下,该后缀为 .
您可以通过设置属性来更改此后缀。.writing
temporary-file-suffix
但是,在某些情况下,您可能不想使用此技术(例如,如果服务器不允许重命名文件)。
对于此类情况,您可以通过设置为 (默认为 ) 来禁用此功能。
当此属性为 时,文件将以其最终名称写入,并且使用应用程序需要某种其他机制来检测文件是否已完全上传,然后再访问它。use-temporary-file-name
false
true
false
使用 Java 配置进行配置
以下 Spring Boot 应用程序显示了如何使用 Java 配置配置出站适配器的示例:
@SpringBootApplication
@IntegrationComponentScan
public class FtpJavaApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context =
new SpringApplicationBuilder(FtpJavaApplication.class)
.web(false)
.run(args);
MyGateway gateway = context.getBean(MyGateway.class);
gateway.sendToFtp(new File("/foo/bar.txt"));
}
@Bean
public SessionFactory<FTPFile> ftpSessionFactory() {
DefaultFtpSessionFactory sf = new DefaultFtpSessionFactory();
sf.setHost("localhost");
sf.setPort(port);
sf.setUsername("foo");
sf.setPassword("foo");
sf.setTestSession(true);
return new CachingSessionFactory<FTPFile>(sf);
}
@Bean
@ServiceActivator(inputChannel = "ftpChannel")
public MessageHandler handler() {
FtpMessageHandler handler = new FtpMessageHandler(ftpSessionFactory());
handler.setRemoteDirectoryExpressionString("headers['remote-target-dir']");
handler.setFileNameGenerator(new FileNameGenerator() {
@Override
public String generateFileName(Message<?> message) {
return "handlerContent.test";
}
});
return handler;
}
@MessagingGateway
public interface MyGateway {
@Gateway(requestChannel = "toFtpChannel")
void sendToFtp(File file);
}
}
使用 Java DSL 进行配置
以下 Spring Boot 应用程序显示了如何使用 Java DSL 配置出站适配器的示例:
@SpringBootApplication
@IntegrationComponentScan
public class FtpJavaApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context =
new SpringApplicationBuilder(FtpJavaApplication.class)
.web(false)
.run(args);
MyGateway gateway = context.getBean(MyGateway.class);
gateway.sendToFtp(new File("/foo/bar.txt"));
}
@Bean
public SessionFactory<FTPFile> ftpSessionFactory() {
DefaultFtpSessionFactory sf = new DefaultFtpSessionFactory();
sf.setHost("localhost");
sf.setPort(port);
sf.setUsername("foo");
sf.setPassword("foo");
sf.setTestSession(true);
return new CachingSessionFactory<FTPFile>(sf);
}
@Bean
public IntegrationFlow ftpOutboundFlow() {
return IntegrationFlow.from("toFtpChannel")
.handle(Ftp.outboundAdapter(ftpSessionFactory(), FileExistsMode.FAIL)
.useTemporaryFileName(false)
.fileNameExpression("headers['" + FileHeaders.FILENAME + "']")
.remoteDirectory(this.ftpServer.getTargetFtpDirectory().getName())
).get();
}
@MessagingGateway
public interface MyGateway {
@Gateway(requestChannel = "toFtpChannel")
void sendToFtp(File file);
}
}