【问题标题】:Serving dynamic zip files through Apache通过 Apache 提供动态 zip 文件
【发布时间】:2011-01-17 13:18:58
【问题描述】:

我的 Rails 应用程序的职责之一是创建和提供签名的 xml。任何签名的 xml,一旦创建,就永远不会改变。因此,我将每个 xml 存储在 public 文件夹中并适当地重定向客户端以避免来自控制器的不必要处理。

现在我想要一个新功能:每个 xml 都与一个日期相关联,我想实现提供一个压缩文件的功能,该文件包含每个 xml,其日期位于客户端指定的时间段内。尽管如此,该功能的使用期限不能限制为少于一个月,这意味着提供的某些 zip 文件将高达 50M。

我的应用程序被部署为 Apache 的乘客模块。因此,使用send_data 提供文件是完全不可接受的,因为客户端必须等待整个压缩文件生成后才能开始实际下载。虽然我对如何在 Rails 中实现该功能以便在提供服务时生成压缩文件有一个想法,但我觉得一旦分配了一些冗长的 Ruby/Passenger 进程来提供服务,我的服务器就会变得稀缺资源大 zip 文件。

我读过a better solution 通过 Apache 提供静态文件,而不是动态文件。

那么,解决问题的方法是什么?我需要像自定义 Apache 处理程序这样的东西吗?如何从我的应用程序中通知 Apache 如何处理请求、压缩文件并同时流式传输结果?

【问题讨论】:

  • ZIP 文件格式索引位于文件末尾。此外,我快速浏览了 RFC 2616 (HTTP 1.1),虽然通常应该公布内容长度,但这样的可变长度响应可能有效。据我所知,从技术上讲,这应该是可能的。
  • 事先不知道长度是没有HTTP问题的,这就是分块传输编码的用处。您可以使用任何语言编写看起来像 zip 文件的字节,只要确保定期刷新输出即可。

标签: apache zip streaming


【解决方案1】:

查看我的 Nginx 的 mod_zip 模块:

http://wiki.nginx.org/NgxZip

您可以让后端脚本告诉 Nginx 哪些 URL 位置包含在存档中,Nginx 将动态地将 ZIP 文件流式传输到包含这些文件的客户端。该模块利用 Nginx 的单线程代理代码,非常轻量级。

该模块于 2008 年首次发布,目前已相当成熟。根据您的描述,我认为它会满足您的需求。

【讨论】:

    【解决方案2】:

    您只需使用可用的任何 API 创建一个 zip 文件并将其写入响应,定期刷新输出。如果这是为大型 zip 文件提供服务,或者会经常被请求,请考虑在具有高 nice/ionice 值/低优先级的单独进程中运行它。

    最坏的情况是,您可以在低优先级进程中运行命令行 zip 并定期传递输出。

    【讨论】:

      【解决方案3】:

      这很棘手,但我已经制作了一个名为 zipline (http://github.com/fringd/zipline) 的 gem,它可以让事情为我工作。我想更新它以便它可以支持普通文件句柄或路径,现在它假设您使用的是carrierwave...

      另外,您可能无法与乘客一起流式传输响应...我必须使用 unicorn 才能使流式传输正常工作...某些机架中间件甚至会搞砸(调用 response.to_s 会破坏它)

      如果有人仍然需要这个在 github 页面上打扰我

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-27
        • 2015-11-20
        • 1970-01-01
        • 2011-01-16
        • 2015-03-18
        • 2019-02-22
        • 2023-03-18
        相关资源
        最近更新 更多