За последние 24 часа нас посетили 22418 программистов и 1061 робот. Сейчас ищут 679 программистов ...

Ошибка в IE при сжатии gzip

Тема в разделе "PHP для новичков", создана пользователем AterCattus, 23 июл 2008.

  1. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Где-то как-то сталкивался с тем, что IE некорректно распаковывает полученную страницу. И для исправления данного недоразумения предлагалось перед самой страницей выдавать что-то около 2КБ пробелов (&032).
    Кто что знает по этому поводу? Подробности, ссылки и т.п.
     
  2. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    AterCattus
    Никогда не слышал о таком, всегда сжимаю контент перед отдачей, никогда не жаловались (IE 5-6-7).
    И если уж добавлять балласт, то ни в коем случае не ПЕРЕД данными, а ПОСЛЕ.

    Кстати, небольшая деталь: я пользуюсь не стандартным ob_gzhandler, а своим обработчиком. Единственная разница - мой обработчик корректно посылает заголовок Content-Length.
     
  3. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    У меня никаких проблем на FF и Safari. В IE7 тоже все ок. У меня. Но есть глюки на сторонних машинах под MyIE (на основе IE6).
    У меня у самого свой обработчик. Смотрел несколько сторонних CMS/CMF, но только у Битрикса идет свой обработчик.
    И в нем нашел вот такой занятный код:
    PHP:
    1. <?php           if(!defined("BX_SPACES_DISABLED") || BX_SPACES_DISABLED!==true)
    2.                 if((strpos($GLOBALS["HTTP_USER_AGENT"], "MSIE 5")>0 || strpos($GLOBALS["HTTP_USER_AGENT"], "MSIE 6.0")>0) && strpos($GLOBALS["HTTP_USER_AGENT"], "Opera")===false)
    3.                     $Contents = str_repeat(" ", 2048)."\r\n".$Contents; ?>
    Значит все-таки что-то в этом есть?

    Я пробовал много разных вариантов, но вот базовый:
    PHP:
    1. <?php           $content = /* str_repeat( ' ', 2048 ) . */ ob_get_clean();
    2.             $len = strlen( $content );
    3.             $crc32 = crc32( $content );
    4.            
    5.             // сжатие
    6.             $content = gzcompress( $content, $this->config( 'compression_level', 5 ) );
    7.             if ( $content === FALSE ) return FALSE;
    8.             $content = substr( $content, 0, -4 );
    9.            
    10.             header( 'Content-Encoding: ' . $this->acceptEncoding() );
    11.             /* header( 'Content-Length: ' . strlen( $content ) ); */
    12.             echo "\x1f\x8b\x08\x00\x00\x00\x00\x00";
    13.             echo $content;
    14.             echo pack( 'V', $crc32 );
    15.             echo pack( 'V', $len ); ?>
    Закоментированы варианты. Content-Length по RFC по желанию, а не обязательно.
     
  4. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Сделал такой вариант:
    PHP:
    1. <?php           $content = ob_get_clean() . str_repeat( ' ', 2048 );
    2.             $len = strlen( $content );
    3.             $crc32 = crc32( $content );
    4.            
    5.             // сжатие
    6.             $content = gzcompress( $content, $this->config( 'compression_level', 5 ) );
    7.             if ( $content === FALSE ) return FALSE;
    8.             $content = substr( $content, 0, -4 );
    9.            
    10.             header( 'Content-Encoding: ' . $this->acceptEncoding() );
    11.             header('Vary: Accept-Encoding');
    12.             header( 'Content-Length: ' . strlen( $content ) );
    13.             echo "\x1f\x8b\x08\x00\x00\x00\x00\x00";
    14.             echo $content;
    15.             echo pack( 'V', $crc32 );
    16.             echo pack( 'V', $len ); ?>
    Работает везде, вроде. Но неужто придется мириться с этими лишними 2КБ? Понятно, что в сжатом виде они займут всего несколько бит, но все же...
     
  5. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    AterCattus
    Ох, не стал бы я брать Битрикс в качестве образца...
    *звуки тошноты*

    Разумеется. Но с ним лучше.
     
  6. lexa

    lexa Активный пользователь

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    AterCattus, уровень компрессии по умолчанию замени на 3. Больше не имеет смысла, т.к. сжимать не будет, а процессор тратить - да.
     
  7. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Dagdamor
    Битрикс я взял постольку-поскольку в нем предпринята попытка решить некую проблему. Я так понимаю, что они не просто так это написали. Про $GLOBALS я ничего хорошего не скажу, пример привел именно с целью показать str_repeat( ' ', 2048 ).

    Не раз сегодня читал, что есть некоторые проблемы с IE и Opera для Content-Length + Content-Encoding + gzip. Вот и спрашивал.

    lexa
    Уровень компрессии тут только для примера. В конфиге, который собственно и читается вызовом $this->config() вообще задано 1. На моих страницах ( порядка 2КБ ) при локальной работе это все роли не играет, а т.к. проект в начальном развитии, то я пока не парюсь по этим мелочам. Да, если честно, этот совет - оффтоп ;-)

    [жуткий offtop]Степень сжатия - это скорее расход памяти на словарь, а не процессора.[/жуткий offtop]