SFTP 出站通道介面卡

SFTP出站通道介面卡是一個特殊的 MessageHandler,它連線到遠端目錄併為收到的每個作為傳入 Message 的 payload 的檔案啟動檔案傳輸。它還支援檔案的多種表示形式,因此您不限於 File 物件。與FTP出站介面卡類似,SFTP出站通道介面卡支援以下payload:

  • java.io.File:實際的檔案物件

  • byte[]:表示檔案內容的位元組陣列

  • java.lang.String:表示檔案內容的文字

  • java.io.InputStream:要傳輸到遠端檔案的資料流

  • org.springframework.core.io.Resource:要傳輸到遠端檔案的資料資源

以下示例展示瞭如何配置SFTP出站通道介面卡:

<int-sftp:outbound-channel-adapter id="sftpOutboundAdapter"
    session-factory="sftpSessionFactory"
    channel="inputChannel"
    charset="UTF-8"
    remote-file-separator="/"
    remote-directory="foo/bar"
    remote-filename-generator-expression="payload.getName() + '-mysuffix'"
    filename-generator="fileNameGenerator"
    use-temporary-filename="true"
    chmod="600"
    mode="REPLACE"/>

有關這些屬性的更多詳細資訊,請參閱schema

SpEL和SFTP出站介面卡

與Spring Integration中的許多其他元件一樣,您可以透過指定兩個屬性:remote-directory-expressionremote-filename-generator-expression前面描述過)來配置SFTP出站通道介面卡時使用Spring表示式語言(SpEL)。表示式評估上下文將訊息作為其根物件,這使您可以使用可以根據訊息中的資料(來自“payload”或“headers”)動態計算檔名或現有目錄路徑的表示式。在前面的示例中,我們定義了 remote-filename-generator-expression 屬性,其表示式值根據原始名稱計算檔名,同時附加字尾:'-mysuffix'。

從版本4.1開始,您可以在傳輸檔案時指定 mode。預設情況下,現有檔案會被覆蓋。這些模式由 FileExistsMode 列舉定義,其中包括以下值:

  • REPLACE(預設)

  • REPLACE_IF_MODIFIED

  • APPEND

  • APPEND_NO_FLUSH

  • IGNORE

  • FAIL

使用 IGNOREFAIL 時,檔案不會被傳輸。FAIL 會導致丟擲異常,而 IGNORE 會靜默忽略傳輸(儘管會生成 DEBUG 日誌條目)。

版本4.3引入了 chmod 屬性,您可以使用它在上傳後更改遠端檔案許可權。您可以使用傳統的Unix八進位制格式(例如,600只允許檔案所有者讀寫)。使用Java配置介面卡時,您可以使用 setChmodOctal("600")setChmod(0600)

避免部分寫入的檔案

處理檔案傳輸時常見的​​問題之一是處理部分檔案的可能性。檔案可能在檔案系統​​中出現,但其傳輸實際上尚未完成。

為了解決這個問題,Spring Integration SFTP介面卡使用一種通用演算法,即檔案在臨時名稱下傳輸,並在完全傳輸後重命名。

預設情況下,每個正在傳輸的檔案都會在檔案系統​​中顯示一個附加字尾,預設情況下為 .writing。您可以透過設定 temporary-file-suffix 屬性來更改它。

但是,在某些情況下,您可能不希望使用此技術(例如,如果伺服器不允許重新命名檔案)。對於這種情況,您可以透過將 use-temporary-file-name 設定為 false 來停用此功能(預設值為 true)。當此屬性為 false 時,檔案會以其最終名稱寫入,並且消費應用程式需要其他機制來檢測檔案完全上傳後才能訪問它。

使用 Java 配置

以下Spring Boot應用程式展示瞭如何使用Java配置出站介面卡的示例:

@SpringBootApplication
@IntegrationComponentScan
public class SftpJavaApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context =
                    new SpringApplicationBuilder(SftpJavaApplication.class)
                        .web(false)
                        .run(args);
        MyGateway gateway = context.getBean(MyGateway.class);
        gateway.sendToSftp(new File("/foo/bar.txt"));
    }

    @Bean
    public SessionFactory<SftpClient.DirEntry> sftpSessionFactory() {
        DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
        factory.setHost("localhost");
        factory.setPort(port);
        factory.setUser("foo");
        factory.setPassword("foo");
        factory.setAllowUnknownKeys(true);
        factory.setTestSession(true);
        return new CachingSessionFactory<SftpClient.DirEntry>(factory);
    }

    @Bean
    @ServiceActivator(inputChannel = "toSftpChannel")
    public MessageHandler handler() {
        SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory());
        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 = "toSftpChannel")
         void sendToSftp(File file);

    }
}

使用 Java DSL 進行配置

以下 Spring Boot 應用程式演示瞭如何使用 Java DSL 配置出站介面卡

@SpringBootApplication
public class SftpJavaApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(SftpJavaApplication.class)
            .web(false)
            .run(args);
    }

    @Bean
    public IntegrationFlow sftpOutboundFlow() {
        return IntegrationFlow.from("toSftpChannel")
            .handle(Sftp.outboundAdapter(this.sftpSessionFactory, FileExistsMode.FAIL)
                         .useTemporaryFileName(false)
                         .remoteDirectory("/foo")
            ).get();
    }

}
© . This site is unofficial and not affiliated with VMware.