2011-04-18 15 views
11

Estaba probando mi sitio web con Page Speed ​​y el resultado fue de alrededor de 70/100. Habilitar la compresión fue el primer factor y el más importante para desacelerarlo.PHP Manual GZip Codificación

Sé que puedo hacer eso modificando el php.ini para hacerlo automáticamente pero estaba más interesado en el método manual (gzencode).

El problema es que todos los navegadores fallan al abrir el sitio web (Firefox: "La página que intentas ver no se puede mostrar porque usa una compresión no válida o no compatible", Chrome: "303, ERR Content Encoding ", etc.) o muestran la cadena codificada.

Live Headers muestra que el navegador acepta la codificación, y la respuesta tiene el tipo de contenido establecido, pero aún falla.

GET/HTTP/1.1 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Encoding: gzip,deflate 

HTTP/1.1 200 OK 
Content-Encoding: gzip 
Content-Length: 5827 
Vary: Accept-Encoding 

private function _compress($data) { 
    //return trim(preg_replace(array('/\>[^\S ]+/s','/[^\S ]+\</s','/(\s)+/s'), array('>','<','\\1'), $data)); 
    $supportsGzip = strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false; 

    ob_start(); 
    if ($supportsGzip) { 
     echo gzencode(trim(preg_replace('/\s+/', ' ', $data)), 9); 
    } else { 
     echo $data; 
    } 

    $content = ob_get_contents(); 
    header("content-type: text/html; charset: UTF-8"); 
    header("cache-control: must-revalidate"); 
    $offset = 60 * 60; 
    $expire = "expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT"; 
    header($expire); 
    header('Content-Length: ' . strlen($content)); 
    header('Vary: Accept-Encoding'); 
    ob_end_clean(); 
    echo $content; 
} 

Si cambio el Content-Encoding a zlib, me sale la cadena codificada:

‹������ÕZÿsÛ¶ÿW^‘¥²o‘¨/–-Ë–Ú؉_Ôµ•õÚ_v I°I‚!A©j–Öºnçÿb·»%ÍÚë²nëå?‘þ›=€¤L)’,ÛIw>ŸEâxïáƒ÷°ùÞ½O¶Ÿï߇Žtlؼµ·» $kŸ•¶ ã^ã<܃•\¾� Ÿº—\¸Ô6ŒûŽ”^Õ0z½^®WÊ ¿m4ÅjÅ°…XÎ’©Ã¦ænS·]#ÌÕF-|8LRPL²ìIÈ»5²-\É\™mô=FÀŒJ5"Ù—RóÝ�³Cý€ÉZ([ÙŠb%¹´YýÑãáîcx}±iD´˜¿KV#4”á§x>¬°à®íÒ ãpÅËæî1øÌ®‘@öm 

Realmente no me importa nada acerca de cómo obtener la compresión tanto como Quiero saber por qué no está funcionando.

Saludos,

+0

1 pregunta interesante – Wh1T3h4Ck5

+0

Si '$ supportsGzip' no debe Content-Length' ser la longitud del contenido gzip en su lugar? – Fanis

+0

@Fanis, contenido contiene el contenido del búfer, ya sea codificado o sin formato, según $ supportsGzip. –

Respuesta

10

Bueno, yo creo que es porque estás tratando de comprimir una cadena vacía.

Tomé su script como usted lo dio, y lo ejecuté en FF e IE.

Ambos fallaron y FF dijo que hubo un problema (como usted describió).

Sin embargo, me di cuenta de que $ data es una cadena vacía.

Cuando configuré $data = "Some test data."; en la parte superior del archivo, funcionó de inmediato (el navegador muestra "Algunos datos de prueba") y revisando Firebug, puedo ver los encabezados correctos.

Content-Encoding gzip 
Content-Length 68 
Vary Accept-Encoding 
Content-Type text/html 

Editar: Además, sólo para señalar, a su if ($supportsGzip) { es un poco extraño, porque su condición demás debe en realidad a cabo $data eco, no $content.

Edit: De acuerdo, en función de su función revisada anterior, hay dos problemas clave.

El problema principal tiene que ver con el hecho de que está borrando sus encabezados llamando al ob_end_clean(). Un comentario en el PHP Docs indica que "ob_end_clean() descarta los encabezados".

Esto significa que cualquier encabezado que establezca antes de llamar al ob_end_clean() se borrará. Además, su función revisada tampoco envía un encabezado de codificación gzip.

Debo decir que probablemente tampoco sea necesario usar ob_start y las funciones relacionadas aquí.Intente lo siguiente:

function _compress($data) { 

    $supportsGzip = strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false; 


    if ($supportsGzip) { 
     $content = gzencode(trim(preg_replace('/\s+/', ' ', $data)), 9); 
     header('Content-Encoding: gzip'); 
    } else { 
     $content = $data; 
    } 

    $offset = 60 * 60; 
    $expire = "expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT"; 

    header("content-type: text/html; charset: UTF-8"); 
    header("cache-control: must-revalidate"); 
    header($expire); 
    header('Content-Length: ' . strlen($content)); 
    header('Vary: Accept-Encoding'); 

    echo $content; 

} 

_compress("Some test data"); 

Esto funciona en IE y FF, pero no tuve tiempo de probar otros navegadores.

Si realmente debe usar ob_start y funciones relacionadas, asegúrese de configurar sus encabezados después de llamar al ob_end_clean().

+0

GZIP no es un algoritmo de encriptación sino un algoritmo de compresión. – Gumbo

+0

@Gumbo Doh, lo siento, el cerebro no piensa bien. Fijo. –

+0

la cadena de datos es un parámetro de función, el código era un fragmento. Incluso probé 'data =" Some string "' y aun así fallé la prueba. –

6

me gustaría sugerir a utilizar http://php.net/manual/de/function.ob-gzhandler.php, esto funciona fuera de la caja para mí:

En mi index.php acabo de colocar esto antes de una salida:

/** 
    * Enable GZIP-Compression for Browser that support it. 
    */ 
    ob_start("ob_gzhandler"); 

Y lo codifica!

+1

'if ($ supportsGzip) { ob_start ("ob_gzhandler"); eco recortar (preg_replace ('/ \ s + /', '', $ data)); } ' intentaron que solía, pero todavía abierta. No se muestra ninguna salida antes de que se llame a esta función. –

+0

que no es necesario si el() delante de ella, porque los cheques PHP por nosotros (de la documentación): (ob_gzhandler) está destinado a ser utilizado como una función de devolución de llamada para ob_start() para ayudar a facilitar el envío de datos codificados mediante gz a los navegadores web que admiten páginas web comprimidas. Antes de que ob_gzhandler() realmente envíe datos comprimidos, determina qué tipo de contenido aceptará el navegador ("gzip", "deflate" o ninguno) y devolverá su resultado en consecuencia. ... Si un navegador no admite páginas comprimidas, esta función devuelve FALSE. – daschl

+0

Hay una forma de comprobar si el usuario admite la codificación del código siguiente al principio del documento: if (substr_count ($ _ SERVER ['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start ("ob_gzhandler"); else ob_start(); no es necesario usar ob_flush (se agrega automáticamente en este caso) – Zydnar

0

algunas cosas:

  1. Es posible que desee añadir otra cabecera: header ('Content-Encoding: gzip');

  2. está usando el ob_end_clean, que elimina todo el contenido se hizo eco/impresa sin enviarlo al navegador. Dependiendo de lo que intentes hacer, puedes usar ob_flush en su lugar.

  3. Para asegurarse de que su salida está almacenada en búfer y manejada (y comprimida si usa la compresión de búfer de salida de PHP), asegúrese de que todas las instrucciones echo/print se colocan ENTRE las cláusulas ob_start y ob_flush.

-y inténtelo de nuevo :)

Cuestiones relacionadas