25

我有一个 Java 文件扫描器应用程序,它使用 FTP 不断扫描服务器上的目录。获取目录的文件列表并一一下载。另一方面,在服务器上,有一个写入这些文件的进程。如果我很幸运,我不会尝试下载不完整的文件,但是我如何确定服务器上的写入过程是否已完成并且文件句柄已关闭,并且文件已准备好下载?

我无法控制服务器上的写入过程。此外,我没有目录的写权限来尝试获取写句柄以检查是否已经打开了写句柄,因此此选项不在讨论范围内。

是否有解决此问题的 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 建议的那样)。您可以通过查看文件大小来优化这一点。
  • 确定文件是否以可靠的顺序连续写入。当你看到文件 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 回答