此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.1Spring中文文档

此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.1Spring中文文档

FTP 出站通道适配器依赖于连接到 FTP 服务器的实现,并为它在传入消息的有效负载中接收的每个文件启动 FTP 传输。 它还支持文件的多种表示形式,因此您不仅限于 -type 有效负载。 FTP 出站通道适配器支持以下有效负载:MessageHandlerjava.io.FileSpring中文文档

以下示例演示如何配置:outbound-channel-adapterSpring中文文档

<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 出站通道适配器,同时还提供各种属性的值,例如(策略接口的实现)、对 的引用和其他属性。 您还可以看到一些属性示例,这些属性允许您使用 SpEL 来配置设置,例如 、 和 (前面示例中所示的 SpEL 替代项)。 与任何允许使用 SpEL 的组件一样,可以通过 'payload' 和 'headers' 变量访问有效负载和消息标头。 有关可用属性的更多详细信息,请参阅架构outbound-channel-adapterfilename-generatoro.s.i.file.FileNameGeneratorsession-factory*expressionremote-directory-expressiontemporary-remote-directory-expressionremote-filename-generator-expressionfilename-generatorSpring中文文档

默认情况下,如果未指定文件名生成器,则 Spring Integration 使用 . 根据 中标头的值(如果存在)确定文件名,或者,如果消息的有效负载已经是 ,则使用该文件的原始名称。o.s.i.file.DefaultFileNameGeneratorDefaultFileNameGeneratorfile_nameMessageHeadersjava.io.File
定义某些值(如 )可能与平台或 FTP 服务器相关。 例如,正如 forum.spring.io/showthread.php?p=333478&posted=1#post333478 上所报告的那样,在某些平台上,您必须在目录定义的末尾添加斜杠(例如,而不是 )。remote-directoryremote-directory="/thing1/thing2/"remote-directory="/thing1/thing2"

从版本 4.1 开始,您可以在传输文件时指定。 默认情况下,将覆盖现有文件。 模式由枚举定义,枚举包括以下值:modeFileExistsModeSpring中文文档

IGNORE并且不要传输文件。 导致引发异常,同时静默地忽略传输(尽管会生成日志条目)。FAILFAILIGNOREDEBUGSpring中文文档

版本 5.2 引入了该属性,您可以使用该属性在上传后更改远程文件权限。 您可以使用传统的 Unix 八进制格式(例如,仅允许文件所有者进行读写)。 使用 java 配置适配器时,可以使用 或 . 仅当 FTP 服务器支持子命令时才适用。chmod600setChmodOctal("600")setChmod(0600)SITE CHMODSpring中文文档

默认情况下,如果未指定文件名生成器,则 Spring Integration 使用 . 根据 中标头的值(如果存在)确定文件名,或者,如果消息的有效负载已经是 ,则使用该文件的原始名称。o.s.i.file.DefaultFileNameGeneratorDefaultFileNameGeneratorfile_nameMessageHeadersjava.io.File
定义某些值(如 )可能与平台或 FTP 服务器相关。 例如,正如 forum.spring.io/showthread.php?p=333478&posted=1#post333478 上所报告的那样,在某些平台上,您必须在目录定义的末尾添加斜杠(例如,而不是 )。remote-directoryremote-directory="/thing1/thing2/"remote-directory="/thing1/thing2"

避免部分写入的文件

处理文件传输时出现的常见问题之一是处理部分文件的可能性。 也就是说,文件在传输实际完成之前可能会出现在文件系统中。Spring中文文档

为了解决这个问题,Spring Integration FTP适配器使用一种通用算法:文件以临时名称传输,然后在完全传输后重命名。Spring中文文档

默认情况下,正在传输的每个文件都会在文件系统中显示一个附加后缀,默认情况下,该后缀为 。 您可以通过设置属性来更改此后缀。.writingtemporary-file-suffixSpring中文文档

但是,在某些情况下,您可能不想使用此技术(例如,如果服务器不允许重命名文件)。 对于此类情况,您可以通过设置为(默认值为 )来禁用此功能。 当此属性为 时,文件将以其最终名称写入,并且使用应用程序需要一些其他机制来检测文件是否已完全上传,然后再访问它。use-temporary-file-namefalsetruefalseSpring中文文档

使用 Java 配置进行配置

以下 Spring Boot 应用程序显示了如何使用 Java 配置配置出站适配器的示例:Spring中文文档

@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 配置出站适配器的示例:Spring中文文档

@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);

    }

}