SFTP 輸出通道配接器
SFTP 輸出通道配接器是一種特殊的 MessageHandler
,它會連線到遠端目錄,並為每個接收為輸入 Message
酬載的檔案啟動檔案傳輸。它也支援檔案的幾種表示方式,因此您不限於 File
物件。與 FTP 輸出配接器類似,SFTP 輸出通道配接器支援下列酬載
-
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 中的許多其他元件一樣,您可以在設定 SFTP 輸出通道配接器時使用 Spring 運算式語言 (SpEL),方法是指定兩個屬性:remote-directory-expression
和 remote-filename-generator-expression
(先前說明)。運算式評估內容會將訊息作為其根物件,讓您可以使用運算式,根據訊息中的資料(來自「酬載」或「標頭」)動態計算檔案名稱或現有目錄路徑。在先前的範例中,我們使用運算式值定義 remote-filename-generator-expression
屬性,該運算式值會根據原始名稱計算檔案名稱,同時附加字尾:「-mysuffix」。
從 4.1 版開始,您可以在傳輸檔案時指定 mode
。預設情況下,現有檔案會被覆寫。模式由 FileExistsMode
列舉定義,其中包括下列值
-
REPLACE
(預設) -
REPLACE_IF_MODIFIED
-
APPEND
-
APPEND_NO_FLUSH
-
IGNORE
-
FAIL
使用 IGNORE
和 FAIL
時,不會傳輸檔案。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();
}
}