防止PHP提供的zip文件被mod_deflate压缩

8
我在防止mod_deflate干扰以下场景方面遇到了一些问题:
  1. 用户运行CodeIgniter(或任何其他重定向到index.php的框架)
  2. mod_deflate处于活动状态
  3. zip文件由CodeIgniter控制器提供服务(headers + readfile)
问题是Apache始终检测到内容为php,因此像下面的代码行这样的东西不起作用,因为服务器会将ZIP文件视为PHP文件。
<FilesMatch "\.(xml|txt|html|php)$">
   SetOutputFilter DEFLATE
</FilesMatch>

有什么想法可以让Apache区分由同一index.php框架文件生成的HTML文件或ZIP文件。
编辑:
apache log
[Mon Jun 20 02:14:19 2011] [debug] 
mod_deflate.c(602): [client 192.168.0.5] 
Zlib: Compressed 50870209 to 50878224 : URL /index.php, 
referer: http://demo.dev/

编辑:
CI控制器用于提供zip文件。

header('Content-Type: application/zip');
header('Content-Transfer-Encoding: binary');
header("Content-Length: " . filesize($file_location)); 
header('Content-Disposition: attachment; filename="' . $file_title . '"'); 
readfile($file_location);

你能展示一下在CodeIgniter中设置头部的代码吗? - Femi
@Femi更新了问题。谢谢! - Frankie
5个回答

6

尽管在合理的情况下所有答案都应该是完全有效的(实际上在提问之前已经进行了测试),但我无法指示Apache按MIME类型压缩文件的原因仍然未知。

通过将以下指令强制添加到脚本中,我能够使其按预期工作

apache_setenv('no-gzip', 1);
ini_set('zlib.output_compression', 0);

我知道这是一个热补丁,并没有解决问题的根本,但目前只能这样。因为可能会有其他人遇到同样的问题,上述代码可作为脏修复的参考。


2
你可以利用mod_rewrite在Apache层面上更改请求的mime类型:了解更多信息
# Serve .zip request as zip-files
RewriteRule \.zip$ - [T=application/zip,E=no-gzip:1]

将其放置在框架规则之上,但需要使DEFLATE也依赖于mime类型而不是像您在<FilesMatch>中使用文件扩展名。

很可能它与以下内容一起正常工作:

AddOutputFilterByType DEFLATE text/html

使用<FilesMatch>指令的替代方法。

编辑:添加了应在.htaccess上下文中使用的L标志,并通过no-gzip环境变量关闭了DEFLATE。


@hakre Apache 仍将该文件视为 php 文件。实际路径是:example.com/files/myfile.zip但某种程度上Apache知道并将其视为 .php 文件。 - Frankie
因为它是磁盘上的 .php 文件(apache 解析的文件)。您需要使 DEFLATE 依赖于 mime 类型。我刚刚编辑了我的答案。 - hakre
@hakre,不幸的是没有运气。我将编辑我的问题以反映我的当前.htaccess文件和httpd.conf - Frankie
重写规则应该是不必要的,因为PHP已经设置了正确的内容类型。 - Artefacto
你误解了意图。它是用于Apache请求处理的MIME类型,而不仅仅是响应HTTP内容类型头。 - hakre
显示剩余3条评论

2
你可以选择以下两种方式之一:
  • 使用已废弃的 AddOutputFilterByType 并仅指定您想要过滤的内容类型; 或者
  • 使用更强大的 mod_filter。在 FilterProvider 中,您可以提供一个规则,当响应头中发现 zip 内容类型 (application/zip) 时,排除该过滤器。

这个单行代码 AddOutputFilterByType DEFLATE text/html 就足以让 Apache 压缩我的伪装 zip 文件。但是它并不会压缩其他文件(所以它基本上还是按照预期工作的)。 - Frankie
@Frankie 这里可以工作。确保您没有在其他地方配置mod_deflate。例如,一些发行版在“/etc/apaches/mods-enabled/deflate.conf”中包含额外的配置。 - Artefacto
谢谢。我没有任何花哨的模块(CentOS),但明天我会清理我的httpd.conf并查看是否能够确定罪犯。谢谢。 - Frankie
安装了一个纯净版的Fedora 15,结果遇到了完全相同的问题。尝试使用不同的替代方案来复制您的设置,但都没有成功。最终,在您提供的出色示例的基础上,找到了以下命令:@apache_setenv('no-gzip', 1);,这是一个明显的赢家。因此,如果您能更新您的答案以包括该命令,我将非常乐意接受它。感谢您的所有帮助。 - Frankie

1
尝试这个(因为你的 URL 似乎以 .zip 结尾,所以这可能适用于你):
<FilesMatch "\.(xml|txt|html|php)$">
   SetEnvIf Request_URI "\.zip$" no-gzip
   SetOutputFilter DEFLATE
</FilesMatch>

谢谢,但不幸的是没有运气。如果我只匹配CSS和JS文件,它会起作用...一旦我将php放入架子上...它就停止工作了。 - Frankie

0

不要使用

<FilesMatch "\.(xml|txt|html|php)$">
   SetOutputFilter DEFLATE
</FilesMatch>

使用此配置来设置压缩规则。

AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml application/x-javascript application/javascript

这样,只有当内容类型与上述指令匹配时,您的输出才会被压缩。

CI控制器已经发送了正确的内容类型头,因此不会被压缩。

header('Content-Type: application/zip');

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接