25

FTPを使用してサーバー上のディレクトリをスキャンし続けるJavaのファイルスキャナーアプリケーションがあります。ディレクトリのファイルのリストを取得し、それらを 1 つずつダウンロードします。一方、サーバーには、これらのファイルを書き込むプロセスがあります。運が良ければ、不完全なファイルをダウンロードしようとはしませんが、サーバーでの書き込みプロセスが完了し、ファイル ハンドルが閉じられ、ファイルをダウンロードする準備ができていることを確認するにはどうすればよいでしょうか。

サーバー上の書き込みプロセスを制御できません。さらに、書き込みハンドルが既に開いているかどうかを確認するために書き込みハンドルを取得しようとするディレクトリへの書き込み権限がないため、このオプションはテーブルから外れています。

この問題に対処する FTP 機能はありますか?

4

4 に答える 4

27

これは非常に古く、よく知られた問題です。

FTP デーモンによって書き込まれるファイルが完全であることを完全に確認する方法はありません。ファイル転送が失敗し、再起動して完了する可能性さえあります。ファイルのサイズをポーリングし、時間制限 (たとえば 5 分) を設定する必要があります。その間にサイズが変わらない場合は、ファイルが完成していると見なされます。

可能であれば、ファイルを処理するプログラムは部分ファイルを処理できる必要があります。

はるかに優れた代替手段は rsync です。これは、はるかに堅牢で決定論的です。データを最初に一時的な場所に書き込み、正常に完了したときに最終的な宛先パスに移動するように (コマンドライン オプションを介して) 構成することもできます。ファイルが期待する場所に存在する場合、そのファイルは定義上完全です。

于 2013-01-22T06:32:26.427 に答える
12

考えられる解決策は、最初に別のファイル名でファイルをアップロードし (たとえば、".partial" を追加)、最終的な名前に名前を変更することです。

サーバーが最終的な名前を見つけたら、アップロードは完了です。

アップロード プロセスを制御できない場合、求めていることは定義上不可能です。ファイルのアップロードは、ネットワークの問題または何らかの理由で送信プロセスが停止したために停止する可能性があります。

受信側が観察するのは、着信ストリームの終了だけです。データが部分的に転送されないことを保証する方法はありません。

他の回避策として、データの終わりのマーカーを確認するか、送信側サーバーへの要求を使用して、(彼らの見解で) 転送が完了したかどうかを確認することができます。

于 2013-01-22T06:37:19.150 に答える
7

これは FTP よりも基本的なことです。これらのファイルがローカル マシンで作成されている場合でも、これらのファイルを読み取る際に同様の問題が発生します。

書き込みプロセスを変更できない場合は、いくつかのフープをジャンプする必要があります. どれも素晴らしいものではありませんが、他よりも安全なものもあります。

  • なんらかのウィンドウ (David Schwartz が示唆するように 1 分程度) で何も変化がなくなるまで読み続けてください。ファイルサイズを監視することで、これを少し最適化できます。
  • ファイルが信頼できる順序で連続して書き込まれているかどうかを調べます。ファイル N が表示されたら、ファイル N-1 の準備ができていることがわかります。(タイムスタンプを確認することもできますが、ファイルが書き込まれる前にディレクトリが空であると仮定します。) 欠点は、ライターが順序を変更したり、並行して書き込みを開始したりすると、ロジックが壊れることです。

信頼できる安全なソリューションには、ライター プロセスの改善が必要です。

  • Writer はファイルを非表示または一時的な場所に書き込み、シンボリック リンクまたはファイル移動または chmod を使用して、ファイル全体 (またはディレクトリ) の準備が整ったときにのみそれらを表示できます。
  • Writer は、他のすべてのファイルが書き込まれた後でのみ、特別なファイル ("./DONE" など) を作成し、そのファイルが存在するまで、reader はファイルを読み取りません。
  • ファイルの種類に応じて、ライターはファイルの末尾にある種のエンドオブファイル レコード/行を追加でき、リーダーはそれが存在することを確認できます。
于 2013-01-22T06:31:58.567 に答える
0

Apache 共通 API から Ftp ライブラリを使用できます 詳細情報を入手する

 boolean flag = retrieveFile(String remote, OutputStream local);

このフラグ チェック出力ストリームは、現在のファイルで使用できます。

于 2013-01-22T06:03:00.493 に答える