Запретить mod_deflate в zip-файле, обслуживаемом PHP

У меня возникли некоторые проблемы, препятствующие включению mod_deflate в этом сценарии:

  1. пользователь, запускающий CodeIgniter (или любой другой фреймворк, который перенаправляет на index.php)
  2. mod_deflate активен
  3. 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');
Другие вопросы по тегам