2012-01-17 17 views
14

Estoy usando la función file_get_contents() de php para hacer una solicitud HTTP. Para ahorrar ancho de banda, decidí agregar el encabezado "Accept-Encoding: gzip" usando stream_context_create().Descomprimir la respuesta http comprimida gzip

Obviamente, file_get_contents() genera una cadena codificada en gzip, así que estoy usando gzuncompress() para decodificar la cadena codificada, pero aparece un error con los datos pasados ​​como argumento.

[...] PHP Warning: gzuncompress(): data error in /path/to/phpscript.php on line 26 

sé que no es otra función capaz de descomprimir los datos gzipped gzdecode() pero no está incluido en mi versión de PHP (tal vez sólo está disponible en SVN).

Sé que cUrl decodifica la transmisión gzip sobre la marcha (sin ningún problema) pero alguien me sugirió que usara file_get_contents() en lugar de cUrl.

¿Conoces alguna otra forma de descomprimir datos comprimidos en PHP o por qué gzuncompress() genera una advertencia? Es absurdo que gzuncompress() no funcione como se esperaba.

Notas: El problema es sin duda acerca de PHP: la solicitud de HTTP se realiza a la API de Tumblr que da una respuesta bien codificada.

+0

¿Conoce por qué se sugiere el uso de 'file_get_contents' vez de cUrl? – Jonathan

+0

No, no sé, dijeron "es mejor". Puedo volver a cUrl, pero de todos modos tengo curiosidad por el problema de gzuncompress(). –

+0

¿Es porque los datos también están codificados en base64? –

Respuesta

12

gzuncompress no funcionará para la codificación gzip. Es la función de descompresión para los archivos .Z.

El manual enumera algunas soluciones para el gzdecode()#82930 que falta, o simplemente use el de upgradephp, o la solución temporal del archivo gzopen temp.

Otra opción sería forzar la codificación deflate con el encabezado Accept-Encoding: y luego usar gzinflate() para la descompresión.

+0

Estoy desarrollando una biblioteca de código abierto, por lo que no puedo obligar a los usuarios a instalar upgradephp. La instalación de la biblioteca debe ser lo más simple posible, así que estoy usando el cUrl que tiene soporte gzip incorporado. –

+0

Uhm, ¿qué? Simplemente puede copiar y pegar la implementación de una sola función, si no desea enviar todo el fragmento upgradephp. – mario

+0

Mario, gracias por su sugerencia, pero acabo de pasar a cUrl, dejando la implementación file_get_contents(). ¿Estás seguro de que la importación de gzdecode() desde upgradephp funcionará sin ninguna otra dependencia? –

26

Encontramos este trabajo para mí: http://www.php.net/manual/en/function.gzdecode.php#106397

Opcionalmente Proveedores: http://digitalpbk.com/php/file_get_contents-garbled-gzip-encoding-website-scraping

if (! function_exists('gzdecode')) 
{ 
    /** 
    * Decode gz coded data 
    * 
    * http://php.net/manual/en/function.gzdecode.php 
    * 
    * Alternative: http://digitalpbk.com/php/file_get_contents-garbled-gzip-encoding-website-scraping 
    * 
    * @param string $data gzencoded data 
    * @return string inflated data 
    */ 
    function gzdecode($data) 
    { 
     // strip header and footer and inflate 

     return gzinflate(substr($data, 10, -8)); 
    } 
} 
+2

Hermoso, he estado buscando todo esto – AlBeebe

+0

Parece que gzinflate no es tan flexible como gzdecode. ejemplo que funciona con gzdecode, pero no con gzinflate: http://cdn.misterwhat.com/mwuk.min.gz.css?ver=3.1 – mgutt

+0

Sí, esto funciona. Debería ser la respuesta aceptada para mí – realtebo

0

Antes datos decomress que necesita para ensamblarlo. Así que si cabecera contiene

Transfer-Encoding: chunked 

que necesita para unchank ella.

function http_unchunk($data) { 
    $res=[]; 
    $p=0; $n=strlen($data); 
    while($p<$n) { 
     if (preg_match("/^([0-9A-Fa-f]+)\r\n/",substr($data,$p,18),$m)) { 
      $sz=hexdec($m[1]); $p+=strlen($m[0]); 
      $res[]=substr($data,$p,$sz); $p+=$sz+2; 
     } else { 
      break; 
     } 
    } 
    return implode('',$res); 
} 

si Content-Encoding es gzip o x-gzip o x-compress uso gzdecode si Content-Encoding es desinflar el uso gzdeflate

... 
if ($chunked) $body=http_unchunk($body); 
if ($gzip) $body=gzdecode($body); 
if ($deflate) $body=gzdeflate($body); 
... 
Cuestiones relacionadas