Запретить mod_deflate в zip-файле, обслуживаемом PHP
У меня возникли некоторые проблемы, препятствующие включению mod_deflate в этом сценарии:
- пользователь, запускающий CodeIgniter (или любой другой фреймворк, который перенаправляет на index.php)
- mod_deflate активен
- zip-файл обслуживается контроллером CodeIgniter (заголовки + readfile)
Дело в том, что Apache всегда обнаруживает контент как php
и поэтому что-то вроде приведенных ниже строк не будет работать, поскольку сервер предполагает, что ZIP-файл является PHP-файлом.
<FilesMatch "\.(xml|txt|html|php)$">
SetOutputFilter DEFLATE
</FilesMatch>
Любые идеи о том, как я могу отличить Apache от HTML-файла или ZIP-файла, сгенерированных одним и тем же index.php
каркасный файл.
Редактировать:
лог apache
[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 контроллер, который обслуживает почтовый индекс
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);
5 ответов
Даже несмотря на то, что все ответы должны были быть абсолютно правильными в разумном сценарии (и были фактически проверены до постановки вопроса), причина, по которой я не смог дать команду Apache дефлировать файл MIME-Type, остается неизвестной.
Я смог заставить его работать так, как нужно, введя в скрипт следующие инструкции
apache_setenv('no-gzip', 1);
ini_set('zlib.output_compression', 0);
Я понимаю, что это горячий патч, и он не затрагивает корень проблемы, но пока этого будет достаточно. Так как есть другие, которые могут нажать тот же флаг, приведенный выше код остается здесь для справки в том, что является грязным исправлением.
Вы также можете:
- использовать устаревший
AddOutputFilterByType
и укажите только те типы контента, которые вы хотите фильтровать; или же - использовать более мощный
mod_filter
, ВFilterProvider
Вы можете предоставить правило, которое исключает фильтр, когда тип содержимого zip (application/zip
) находится в заголовках ответа.
Вы можете использовать mod_rewrite
чтобы изменить mime-тип запроса на уровне Apache:
# Serve .zip request as zip-files
RewriteRule \.zip$ - [T=application/zip,E=no-gzip:1]
Поместите его выше правил фреймворка, однако для этого необходимо, чтобы DEFLATE также зависел от mime-типа, а не от расширения файла, как вы это делаете с <FilesMatch>
,
Вероятно, это хорошо работает вместе с
AddOutputFilterByType DEFLATE text/html
вместо <FilesMatch>
Директива.
Редактировать: Добавлен флаг L, который должен использоваться в контексте.htaccess, и дополнительно отключить DEFLATE через переменную окружения no-gzip.
Попробуйте это (поскольку ваши URL-адреса заканчиваются на.zip, это может сработать для вас):
<FilesMatch "\.(xml|txt|html|php)$">
SetEnvIf Request_URI "\.zip$" no-gzip
SetOutputFilter DEFLATE
</FilesMatch>
Вместо того, чтобы использовать
<FilesMatch "\.(xml|txt|html|php)$">
SetOutputFilter DEFLATE
</FilesMatch>
Используйте эту конфигурацию для настройки правил сжатия.
AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml application/x-javascript application/javascript
Таким образом, ваш вывод будет сжат только в том случае, если тип содержимого соответствует указанным выше директивам.
Контроллер CI, который обслуживает zip, уже отправляет правильный заголовок типа контента, поэтому он не будет сжат.
header('Content-Type: application/zip');