Apache HTTP服务器 – 如何确定服务器上的下载是否完成以及哪个文件?

我们有一个Apache HTTP服务器正在运行,这个服务器为可能有数百兆字节大小的用户提供dynamic创build的zip压缩文件。 当我们每次点击“下载”button时创build一个新文件(即使内容没有改变…),我们很可能会遇到光盘容量问题。

我有一个相当愚蠢的脚本运行,删除90分钟前创build的所有文件。 显然不是一个解决scheme的好处。

我想知道如何从服务器的命令行下载完成,成功与否。 在这种情况下,我可以删除该文件,因为它不会被提供两次。 考虑一下,甚至可能足以检查服务器是否正在使用文件,因为它是在它被提供给客户端之前创build的。

谢谢!

由于删除了一个进程打开的文件句柄的文件,在文件存在的时候,直到句柄closures,你可以立即删除它们,当Apacheclosures文件时,它将被从磁盘中删除。

TRS-80得到了正确的想法,我肯定会推荐走这条路。 如果您在等待传输完成时死机,那么请考虑使用lsof来确定没有人打开文件。 所以,像这样的:

 for file in /directory/full/of/zips/*.zip; do if [ -z "$(lsof $file)" ]; then # Nobody's reading it, delete rm $file fi done 

我看到的第一种方法是parsing服务器状态的结果,以知道下载是否已经开始。 当下载开始时,您可以像TRS-80所说的那样删除文件。 但我不会build议,因为如果你的客户因任何原因断开连接,他将无法重新启动下载。 所以我会parsing日志文件,以了解文件何时被下载。 日志文件中的条目将不会被添加,直到与客户端的连接被closures。 在日志文件中,您将获得向客户端提供的八位字节数,以便您可以与文件大小进行比较以确保他已下载整个文件。

我会提出一个更优雅的解决scheme:

Apache可以进行条件日志logging,日志可以输出到进程。 所以你可以做这样的事情:

 SetEnvIf Request_URI "^/path/to/files/.*\.zip$" deletefile CustomLog "|/path/to/program" "%r" env=deletefile 

程序将在每个请求完成后得到文件名,并可以删除它:

 #!/usr/bin/perl $| = 1; while (<STDIN>) { unlink($_); } 

您甚至可以使用“%> s%r”作为格式,并且只有在状态为200时才能删除。

这不是一个明确的答案,但我首先想到解决这个问题。

我每小时都会运行一个脚本。 该脚本将枚举Zip源文件夹中的所有文件名。 然后,我会让脚本通过Apache日志读取与当前文件名相匹配的某种Transfer Completion条目。 如果有匹配的日志条目,请删除该文件。 如果不是,则转到下一个文件名。

有一些真正伟大的信息在这个页面上。 由于TRS-80的方法的巧妙,我不觉得值得贡献。 但是我担心的是你正在服务巨大的dynamic生成的文件,但担心磁盘空间。 我想确保你对自己最珍贵的资源RAM是明智的。

首先,你必须确保你正在做的事情,使Apache可以利用发送文件。 我也会关心用任何基于模块的应用程序层,mod_php,mod_python或mongrel / Ruby on Rails的反向代理来生成文件。 你真的需要谨慎这一点。 我不太了解你的设置,但本能告诉我你应该:

  1. 使用工人MPM而不是前叉
  2. 如果使用Python,请参阅: WSGI如果使用PHP,请参阅: FastCGI如果Rails看到: Passenger
  3. 不要让用户请求触发文件生成 – 做交付。 使用类似AJAX的模式来:
    1. 队列生成的文件
    2. 定期检查完成
    3. logging下载已经开始(好吧,它即将)
    4. 开始下载
  4. 但是,不要依赖客户端来向您表明您应该删除该文件。 我会定期在“开始日志”上使用lsof进行删除。

当然,在我的行业,我们总是不得不担心能够扩展。 你可能不在乎。

作为另一种select – 我有一个类似的过程,但我不写任何东西到磁盘,因为我服务于多GB的档案。

相反,我只是发出适当的HTTP标头(包括Content-Disposition来设置文件名),然后用适当的标志将它们写入标准输出(stdout)。

至于缩放 – 我有大文件,但不要经常发送它们。 我确实通过了“好的”,所以我可以放弃档案处理的优先权。

我唯一担心的是我的系统无法在没有重新开始的情况下恢复部分传输,但是您已经明确表示要清除成功传输和不成功传输。