SFTP 送信ゲートウェイ
SFTP 送信ゲートウェイは、リモート SFTP サーバーとやり取りできる限られたコマンドセットを提供します。
ls
(リストファイル)nlst
(リストファイル名)get
(ファイルを取得する)mget
(複数のファイルを取得する)rm
(ファイルを削除)mv
(ファイルの移動と名前変更)put
(ファイルを送る)mput
(複数のファイルを送信する)
ls
コマンドの使用
ls
はリモートファイルをリストし、次のオプションをサポートします。
-1
: ファイル名のリストを取得します。デフォルトでは、FileInfo
オブジェクトのリストを取得します-a
: すべてのファイルを含める ( "." で始まるものを含む)-f
: リストをソートしないでください-dirs
: インクルードディレクトリ (デフォルトで除外)-links
: シンボリックリンクを含める (デフォルトで除外)-R
: リモートディレクトリを再帰的にリストする
さらに、ファイル名のフィルタリングは inbound-channel-adapter
と同じ方法で提供されます。
ls
操作から生じるメッセージペイロードは、ファイル名のリストまたは FileInfo
オブジェクトのリストです(-1
スイッチを usr するかどうかによって異なります)。これらのオブジェクトは、変更された時間、権限などの情報を提供します。
ls
コマンドが実行されたリモートディレクトリは、file_remoteDirectory
ヘッダーで提供されます。
再帰オプション(-R
)を使用する場合、fileName
にはサブディレクトリ要素が含まれ、ファイルへの相対パス(リモートディレクトリに対する相対パス)を表します。-dirs
オプションを使用する場合、各再帰ディレクトリもリスト内の要素として返されます。この場合、-1
オプションを使用しないことをお勧めします。FileInfo
オブジェクトを使用するとファイルとディレクトリを区別できなくなるためです。
リストする リモートのパスが /
記号で始まる場合、SFTP では現在のユーザーホームの相対パスとしてではなく、絶対パスとして扱われます。
nlst
コマンドの使用
バージョン 5 では、nlst
コマンドのサポートが導入されました。
nlst
はリモートファイル名をリストし、1 つのオプションのみをサポートします。
-f
: リストをソートしないでください
nlst
操作から生じるメッセージペイロードは、ファイル名のリストです。
file_remoteDirectory
ヘッダーには、nlst
コマンドが実行されたリモートディレクトリが保持されます。
SFTP プロトコルは、名前をリストする機能を提供しません。このコマンドは、-1
オプションを指定した ls
コマンドに相当し、便宜上ここに追加されます。
get
コマンドの使用
get
はリモートファイルを取得し、次のオプションをサポートします。
-P
: リモートファイルのタイムスタンプを保持します。-stream
: リモートファイルをストリームとして取得します。-D
: 転送に成功したら、リモートファイルを削除します。FileExistsMode
はIGNORE
であり、ローカルファイルがすでに存在するため、転送が無視される場合、リモートファイルは削除されません。
file_remoteDirectory
ヘッダーはリモートディレクトリを保持し、file_remoteFile
ヘッダーはファイル名を保持します。
get
操作の結果として得られるメッセージペイロードは、取得されたファイルを表す File
オブジェクトです。-stream
オプションを使用する場合、ペイロードは File
ではなく InputStream
になります。テキストファイルの場合、一般的な使用例は、この操作をファイルスプリッターまたはストリームトランスフォーマーと組み合わせることです。リモートファイルをストリームとして使用する場合、ストリームの使用後に Session
を閉じる必要があります。便宜上、Session
は closeableResource
ヘッダーで提供され、IntegrationMessageHeaderAccessor
は便利なメソッドを提供します。
Closeable closeable = new IntegrationMessageHeaderAccessor(message).getCloseableResource();
if (closeable != null) {
closeable.close();
}
次の例は、ファイルをストリームとして使用する方法を示しています。
<int-sftp:outbound-gateway session-factory="ftpSessionFactory"
request-channel="inboundGetStream"
command="get"
command-options="-stream"
expression="payload"
remote-directory="ftpTarget"
reply-channel="stream" />
<int-file:splitter input-channel="stream" output-channel="lines" />
カスタムコンポーネントで入力ストリームを使用する場合は、Session を閉じる必要があります。次の例に示すように、カスタムコードでそれを行うか、メッセージのコピーを service-activator にルーティングして SpEL を使用できます。 |
<int:service-activator input-channel="closeSession"
expression="headers['closeableResource'].close()" />
mget
コマンドの使用
mget
は、パターンに基づいて複数のリモートファイルを取得し、次のオプションをサポートします。
-P
: リモートファイルのタイムスタンプを保持します。-R
: ディレクトリツリー全体を再帰的に取得します。-x
: パターンに一致するファイルがない場合は例外をスローします(そうでない場合は空のリストが返されます)。-D
: 転送が成功したら、各リモートファイルを削除します。転送が無視された場合、FileExistsMode
はIGNORE
であり、ローカルファイルがすでに存在するため、リモートファイルは削除されません。
mget
操作の結果のメッセージペイロードは、List<File>
オブジェクト(つまり、File
オブジェクトの List
、それぞれが取得したファイルを表す)です。
バージョン 5.0 以降、FileExistsMode が IGNORE の場合、出力メッセージのペイロードには、ファイルがすでに存在するためにフェッチされなかったファイルが含まれなくなりました。以前は、配列には既存のファイルを含むすべてのファイルが含まれていました。 |
使用する式は、リモートパスが *
で終わる結果を生成する必要があることを決定します。たとえば、myfiles/*
は myfiles
の完全なツリーをフェッチします。
バージョン 5.0 以降、FileExistsMode.REPLACE_IF_MODIFIED
モードと組み合わせて再帰的な MGET
を使用して、リモートディレクトリツリー全体を定期的にローカルに同期できます。このモードは、-P
(タイムスタンプを保持)オプションに関係なく、ローカルファイルの最終変更タイムスタンプをリモートファイルのタイムスタンプに設定します。
再帰を使用する場合の注意 ( -R ) パターンは無視され、 サブディレクトリをフィルタリングすると、そのサブディレクトリの追加の走査は実行されません。
通常、リモートディレクトリ構造がローカルに保持されるように、 |
永続ファイルリストフィルターにブールプロパティ forRecursion
が追加されました。このプロパティを true
に設定すると、alwaysAcceptDirectories
も設定されます。これは、送信ゲートウェイ(ls
および mget
)での再帰操作が常にディレクトリツリー全体を毎回トラバースすることを意味します。これは、ディレクトリツリーの奥深くで変更が検出されなかった問題を解決するためです。さらに、forRecursion=true
により、ファイルへのフルパスがメタデータストアキーとして使用されます。これにより、同じ名前のファイルが異なるディレクトリに複数回表示された場合にフィルターが正しく機能しなかった問題が解決されます。重要: これは、永続メタデータストア内の既存のキーが、最上位ディレクトリにあるファイルで見つからないことを意味します。このため、プロパティはデフォルトで false
です。これは将来のリリースで変更される可能性があります。
バージョン 5.0 から、alwaysAcceptDirectorties
を true
に設定することにより、常にディレクトリを渡すように SftpSimplePatternFileListFilter
および SftpRegexPatternFileListFilter
を構成できます。これにより、次の例に示すように、単純なパターンの再帰が可能になります。
<bean id="starDotTxtFilter"
class="org.springframework.integration.sftp.filters.SftpSimplePatternFileListFilter">
<constructor-arg value="*.txt" />
<property name="alwaysAcceptDirectories" value="true" />
</bean>
<bean id="dotStarDotTxtFilter"
class="org.springframework.integration.sftp.filters.SftpRegexPatternFileListFilter">
<constructor-arg value="^.*\.txt$" />
<property name="alwaysAcceptDirectories" value="true" />
</bean>
ゲートウェイで filter
プロパティを使用して、これらのフィルターのいずれかを提供できます。
送信ゲートウェイの部分的な成功 (mget
および mput
) も参照してください。
put
コマンドの使用
put
はファイルをリモートサーバーに送信します。メッセージのペイロードは、java.io.File
、byte[]
、String
にすることができます。remote-filename-generator
(または式)は、リモートファイルに名前を付けるために使用されます。その他の使用可能な属性には、remote-directory
、temporary-remote-directory
、それらに相当する *-expression
(use-temporary-file-name
および auto-create-directory
)が含まれます。詳細については、スキーマのドキュメント [GitHub] (英語) を参照してください。
put
操作から生じるメッセージペイロードは、転送後のサーバー上のファイルの完全パスを含む String
です。
バージョン 4.3 では chmod
属性が導入され、アップロード後にリモートファイルのアクセス許可が変更されます。従来の Unix 8 進形式を使用できます(たとえば、600
では、ファイル所有者に対してのみ読み取り / 書き込みが許可されます)。java を使用してアダプターを構成する場合、setChmod(0600)
を使用できます。
mput
コマンドの使用
mput
は複数のファイルをサーバーに送信し、次のオプションをサポートします。
-R
: 再帰 — ディレクトリとサブディレクトリ内のすべてのファイルを送信します(フィルタリングされている場合もあります)
メッセージペイロードは、ローカルディレクトリを表す java.io.File
(または String
)でなければなりません。バージョン 5.1 以降、File
または String
のコレクションもサポートされています。
put
コマンドと同じ属性がサポートされています。さらに、mput-pattern
、mput-regex
、mput-filter
または mput-filter-expression
のいずれかを使用して、ローカルディレクトリ内のファイルをフィルタリングできます。サブディレクトリ自体がフィルターを通過する限り、フィルターは再帰で機能します。フィルターを通過しないサブディレクトリは再帰されません。
mput
操作から生じるメッセージペイロードは、List<String>
オブジェクト(つまり、転送から生じるリモートファイルパスの List
)です。
送信ゲートウェイの部分的な成功 (mget
および mput
) も参照してください。
バージョン 4.3 では、chmod
属性が導入されました。これにより、アップロード後にリモートファイルの権限を変更できます。従来の Unix 8 進形式を使用できます(たとえば、600
では、ファイル所有者に対してのみ読み取り / 書き込みが許可されます)。Java を使用してアダプターを構成する場合、setChmodOctal("600")
または setChmod(0600)
を使用できます。
rm
コマンドの使用
rm
コマンドにはオプションがありません。
削除操作が成功した場合、結果のメッセージペイロードは Boolean.TRUE
です。それ以外の場合、メッセージペイロードは Boolean.FALSE
です。file_remoteDirectory
ヘッダーはリモートディレクトリを保持し、file_remoteFile
ヘッダーはファイル名を保持します。
mv
コマンドの使用
mv
コマンドにはオプションがありません。
expression
属性は "from" パスを定義し、rename-expression
属性は "to" パスを定義します。デフォルトでは、rename-expression
は headers['file_renameTo']
です。この式は、null または空の String
と評価されてはなりません。必要に応じて、必要なリモートディレクトリが作成されます。結果メッセージのペイロードは Boolean.TRUE
です。file_remoteDirectory
ヘッダーは元のリモートディレクトリを保持し、file_remoteFile
ヘッダーはファイル名を保持します。file_renameTo
ヘッダーは新しいパスを保持します。
バージョン 5.5.6 以降、remoteDirectoryExpression
を mv
コマンドで使用できるようになりました。"from" ファイルが完全なファイルパスでない場合、remoteDirectoryExpression
の結果がリモートディレクトリとして使用されます。同じことが "to" ファイルにも当てはまります。たとえば、タスクがディレクトリ内のリモートファイルの名前を変更するだけの場合です。
追加のコマンド情報
get
および mget
コマンドは、local-filename-generator-expression
属性をサポートしています。転送中にローカルファイルの名前を生成する SpEL 式を定義します。評価コンテキストのルートオブジェクトはリクエストメッセージです。remoteFileName
変数も使用できます。mget
で特に役立ちます(例: local-filename-generator-expression="#remoteFileName.toUpperCase() + headers.foo"
)。
get
および mget
コマンドは、local-directory-expression
属性をサポートしています。転送中にローカルディレクトリの名前を生成する SpEL 式を定義します。評価コンテキストのルートオブジェクトはリクエストメッセージです。remoteDirectory
変数も使用できます。mget で特に役立ちます(例: local-directory-expression="'/tmp/local/' + #remoteDirectory.toUpperCase() + headers.myheader"
)。この属性は、local-directory
属性と相互に排他的です。
すべてのコマンドについて、ゲートウェイの「式」プロパティは、コマンドが動作するパスを保持します。mget
コマンドの場合、式は *
に評価される場合があります。これは、すべてのファイル somedirectory/*
、および *
で終わるその他の値を取得することを意味します。
次の例は、ls
コマンド用に構成されたゲートウェイを示しています。
<int-ftp:outbound-gateway id="gateway1"
session-factory="ftpSessionFactory"
request-channel="inbound1"
command="ls"
command-options="-1"
expression="payload"
reply-channel="toSplitter"/>
toSplitter
チャネルに送信されるメッセージのペイロードは、String
オブジェクトのリストであり、各オブジェクトにはファイルの名前が含まれています。command-options="-1"
を省略した場合、ペイロードは FileInfo
オブジェクトのリストになります。オプションをスペース区切りリストとして提供できます(例: command-options="-1 -dirs -links"
)。
バージョン 4.2 以降、GET
、MGET
、PUT
、MPUT
コマンドは FileExistsMode
プロパティ(名前空間サポートを使用する場合は mode
)をサポートします。これは、ローカルファイルが存在する場合(GET
および MGET
)またはリモートファイルが存在する場合(PUT
および MPUT
)の動作に影響します。サポートされているモードは REPLACE
、APPEND
、FAIL
、IGNORE
です。下位互換性のために、PUT
および MPUT
操作のデフォルトモードは REPLACE
です。GET
および MGET
操作の場合、デフォルトは FAIL
です。
Java 構成を使用した構成
次の Spring Boot アプリケーションは、Java で送信ゲートウェイを構成する方法の例を示しています。
@SpringBootApplication
public class SftpJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(SftpJavaApplication.class)
.web(false)
.run(args);
}
@Bean
@ServiceActivator(inputChannel = "sftpChannel")
public MessageHandler handler() {
return new SftpOutboundGateway(ftpSessionFactory(), "ls", "'my_remote_dir/'");
}
}
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 SessionFactory<SftpClient.DirEntry> sftpSessionFactory() {
DefaultSftpSessionFactory sf = new DefaultSftpSessionFactory();
sf.setHost("localhost");
sf.setPort(port);
sf.setUsername("foo");
sf.setPassword("foo");
factory.setTestSession(true);
return new CachingSessionFactory<>(sf);
}
@Bean
public QueueChannelSpec remoteFileOutputChannel() {
return MessageChannels.queue();
}
@Bean
public IntegrationFlow sftpMGetFlow() {
return IntegrationFlow.from("sftpMgetInputChannel")
.handle(Sftp.outboundGateway(sftpSessionFactory(),
AbstractRemoteFileOutboundGateway.Command.MGET, "payload")
.options(AbstractRemoteFileOutboundGateway.Option.RECURSIVE)
.regexFileNameFilter("(subSftpSource|.*1.txt)")
.localDirectoryExpression("'myDir/' + #remoteDirectory")
.localFilenameExpression("#remoteFileName.replaceFirst('sftpSource', 'localTarget')"))
.channel("remoteFileOutputChannel")
.get();
}
}
送信ゲートウェイの部分的な成功 (mget
および mput
)
(mget
および mput
を使用して)複数のファイルで操作を実行する場合、1 つ以上のファイルが転送された後、しばらく時間が経過すると例外が発生することがあります。この場合(バージョン 4.2 以降)、PartialSuccessException
がスローされます。通常の MessagingException
プロパティ(failedMessage
および cause
)と同様に、この例外には 2 つの追加プロパティがあります。
partialResults
: 正常な転送結果。derivedInput
: リクエストメッセージから生成されたファイルのリスト(mput
用に転送するローカルファイルなど)。
これらの属性により、正常に転送されたファイルと転送されなかったファイルを判別できます。
再帰的な mput
の場合、PartialSuccessException
にはネストされた PartialSuccessException
インスタンスがあります。
次のディレクトリ構造を考慮してください。
root/
|- file1.txt
|- subdir/
| - file2.txt
| - file3.txt
|- zoo.txt
file3.txt
で例外が発生した場合、ゲートウェイによってスローされた PartialSuccessException
には、file1.txt
、subdir
、zoo.txt
の derivedInput
と file1.txt
の partialResults
があります。その cause
は、file2.txt
の derivedInput
と file2.txt
の file3.txt
および partialResults
を備えた別の PartialSuccessException
です。