通过 Apache 提供动态 zip 文件
我的 Rails 应用程序的职责之一是创建和提供签名的 xml。任何签名的 xml 一旦创建,就永远不会改变。因此,我将每个 xml 存储在 public
文件夹中,并适当地重定向客户端以避免控制器进行不必要的处理。
现在我想要一个新功能:每个 xml 都与一个日期相关联,并且我想实现提供压缩文件的功能,其中包含日期位于客户端指定的时间段内的每个 xml。然而,该功能的使用期限不能限制在一个月以内,这意味着某些正在提供的 zip 文件将达到 50M 大。
我的应用程序部署为 Apache 的 Passenger 模块。因此,使用 send_data< 提供文件是完全不可接受的/code>
,因为客户端必须等待整个压缩文件生成后才能开始实际下载。虽然我知道如何在 Rails 中实现该功能,以便在提供服务时生成压缩文件,但我觉得一旦分配一些冗长的 Ruby/Passenger 进程来提供服务,我的服务器就会缺乏资源大 zip 文件。
我读过更好的解决方案来提供静态服务文件通过 Apache,但不是动态文件。
那么,解决问题的办法是什么呢?我需要自定义 Apache 处理程序之类的东西吗?我如何从我的应用程序通知 Apache 如何处理请求、压缩文件并同时传输结果?
One of the responsibilities of my Rails application is to create and serve signed xmls. Any signed xml, once created, never changes. So I store every xml in the public
folder and redirect the client appropriately to avoid unnecessary processing from the controller.
Now I want a new feature: every xml is associated with a date, and I'd like to implement the ability to serve a compressed file containing every xml whose date lies in a period specified by the client. Nevertheless, the period cannot be limited to less than one month for the feature to be useful, and this implies some zip files being served will be as big as 50M.
My application is deployed as a Passenger module of Apache. Thus, it's totally unacceptable to serve the file with send_data
, since the client will have to wait for the entire compressed file to be generated before the actual download begins. Although I have an idea on how to implement the feature in Rails so the compressed file is produced while being served, I feel my server will get scarce on resources once some lengthy Ruby/Passenger processes are allocated to serve big zip files.
I've read about a better solution to serve static files through Apache, but not dynamic ones.
So, what's the solution to the problem? Do I need something like a custom Apache handler? How do I inform Apache, from my application, how to handle the request, compressing the files and streaming the result simultaneously?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
查看我的 Nginx mod_zip 模块:
http://wiki.nginx.org/NgxZip 后端脚本告诉 Nginx 将哪些 URL 位置包含在存档中,Nginx 将动态地将 ZIP 文件流式传输到包含这些文件的客户端。该模块利用 Nginx 的单线程代理代码,并且非常轻量级。
该模块于 2008 年首次发布,目前已经相当成熟。根据你的描述,我认为它会满足你的需求。
Check out my mod_zip module for Nginx:
http://wiki.nginx.org/NgxZip
You can have a backend script tell Nginx which URL locations to include in the archive, and Nginx will dynamically stream a ZIP file to the client containing those files. The module leverages Nginx's single-threaded proxy code and is extremely lightweight.
The module was first released in 2008 and is fairly mature at this point. From your description I think it will suit your needs.
您只需使用可用的任何 API 来创建 zip 文件并将其写入响应,定期刷新输出。如果这是提供大型 zip 文件,或者会频繁请求,请考虑在具有高 Nice/ionice 值/低优先级的单独进程中运行它。
最坏的情况是,您可以在低优先级进程中运行命令行 zip 并定期传递输出。
You simply need to use whatever API you have available for you to create a zip file and write it to the response, flushing the output periodically. If this is serving large zip files, or will be requested frequently, consider running it in a separate process with a high nice/ionice value / low priority.
Worst case, you could run a command-line zip in a low priority process and pass the output along periodically.
这很难做到,但我制作了一个名为 zipline 的 gem ( http://github.com/fringd/zipline< /a> )这让事情对我有用。我想更新它,以便它可以支持纯文件句柄或路径,现在它假设您正在使用载波...
另外,您可能无法与乘客传输响应...我不得不使用独角兽来制作流媒体工作正常......并且某些机架中间件甚至可以搞砸(调用response.to_s会破坏它)
如果有人仍然需要这个麻烦我在github页面上
it's tricky to do, but I've made a gem called zipline ( http://github.com/fringd/zipline ) that gets things working for me. I want to update it so that it can support plain file handles or paths, right now it assumes you're using carrierwave...
also, you probably can't stream the response with passenger... I had to use unicorn to make streaming work properly... and certain rack middleware can even screw that up (calling response.to_s breaks it)
if anybody still needs this bother me on the github page