SFTP 送信チャネルアダプター
SFTP 発信チャネルアダプターは、リモートディレクトリに接続し、受信 Message
のペイロードとして受信するすべてのファイルに対してファイル転送を開始する特別な MessageHandler
です。また、ファイルのいくつかの表現もサポートしているため、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"/>
これらの属性の詳細については、スキーマ [GitHub] (英語) を参照してください。
SpEL と SFTP 送信アダプター
Spring Integration の他の多くのコンポーネントと同様に、SFTP 送信チャネルアダプターを構成するときに、remote-directory-expression
と remote-filename-generator-expression
( 前述 ) の 2 つの属性を指定することで、Spring 式言語 (SpEL) を使用できます。式評価コンテキストにはルートオブジェクトとしてメッセージがあり、メッセージ内のデータ (「ペイロード」または「ヘッダー」から) に基づいてファイル名または既存のディレクトリパスを動的に計算できる式を使用できます。前の例では、元の名前に基づいてファイル名を計算し、サフィックス "-mysuffix" も追加する式の値を使用して remote-filename-generator-expression
属性を定義します。
バージョン 4.1 以降、ファイルを転送するときに mode
を指定できます。デフォルトでは、既存のファイルは上書きされます。モードは、次の値を含む FileExistsMode
列挙によって定義されます。
REPLACE
(default)REPLACE_IF_MODIFIED
APPEND
APPEND_NO_FLUSH
IGNORE
FAIL
IGNORE
および FAIL
では、ファイルは転送されません。FAIL
は例外をスローしますが、IGNORE
は通知なしで転送を無視します(DEBUG
ログエントリは生成されます)。
バージョン 4.3 は chmod
属性を導入しました。これを使用して、アップロード後にリモートファイルの許可を変更できます。従来の Unix 8 進形式を使用できます(たとえば、600
では、ファイル所有者に対してのみ読み取り / 書き込みが許可されます)。java を使用してアダプターを構成する場合、setChmodOctal("600")
または setChmod(0600)
を使用できます。
部分的に書き込まれたファイルの回避
ファイル転送を処理する際の一般的な問題の 1 つは、部分的なファイルを処理する可能性です。転送が実際に完了する前に、ファイルがファイルシステムに表示される場合があります。
この課題に対処するために、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();
}
}