2012-01-17 55 views
14

Tôi đang sử dụng chức năng file_get_contents() của php để thực hiện yêu cầu HTTP. Để tiết kiệm băng thông, tôi quyết định thêm tiêu đề "Accept-Encoding: gzip" bằng cách sử dụng stream_context_create().Giải nén phản hồi http đã nén gzip

Rõ ràng, file_get_contents() xuất ra chuỗi được mã hóa gzip vì vậy tôi đang sử dụng gzuncompress() để giải mã chuỗi được mã hóa nhưng tôi gặp lỗi với dữ liệu được truyền làm đối số.

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

Tôi biết có một chức năng có thể giải nén dữ liệu đã giải nén gzdecode() nhưng nó không được bao gồm trong phiên bản PHP của tôi (có lẽ nó chỉ có sẵn trên SVN).

Tôi biết rằng cUrl giải mã luồng gzip khi đang di chuyển (không có bất kỳ vấn đề nào) nhưng ai đó đã đề xuất tôi sử dụng file_get_contents() thay vì cUrl.

Bạn có biết cách nào khác để giải nén dữ liệu đã nén trong PHP hoặc tại sao gzuncompress() xuất ra Cảnh báo không? Thật là vô lý rằng gzuncompress() không hoạt động như mong đợi.

Ghi chú: Vấn đề chắc chắn về PHP: yêu cầu HTTP được thực hiện cho API Tumblr cung cấp phản hồi được mã hóa tốt.

+0

Bạn có biết tại sao họ lại đề nghị để sử dụng 'file_get_contents' thay của cUrl? – Jonathan

+0

Không, tôi không biết, họ nói "nó tốt hơn". Tôi có thể quay lại cUrl nhưng tôi vẫn tò mò về vấn đề gzuncompress(). –

+0

Có phải vì dữ liệu được mã hóa base64 không? –

Trả lời

12

gzuncompress sẽ không hoạt động đối với mã hóa gzip. Đó là chức năng giải nén cho các lưu trữ .Z.

Hướng dẫn liệt kê một vài cách giải quyết cho thiếu gzdecode()#82930 hoặc chỉ sử dụng một từ upgradephp hoặc giải pháp tệp tạm thời của gzopen.

Một tùy chọn khác sẽ buộc mã hóa deflate với tiêu đề Accept-Encoding: và sau đó sử dụng gzinflate() để giải nén.

+0

Tôi đang phát triển một thư viện nguồn mở vì vậy tôi không thể buộc người dùng phải cài đặt upgradephp. Việc cài đặt thư viện phải đơn giản nhất có thể vì vậy tôi đang chuyển sang sử dụng cUrl có hỗ trợ gzip được tích hợp sẵn. –

+0

Uhm, cái gì? Bạn chỉ có thể sao chép và dán thực hiện chức năng duy nhất đó, nếu bạn không muốn gửi toàn bộ đoạn mã nâng cấp cùng. – mario

+0

Mario, cảm ơn đề xuất của bạn nhưng tôi vừa chuyển sang cUrl để lại việc thực hiện file_get_contents(). Bạn có chắc chắn rằng nhập gzdecode() từ upgradephp sẽ làm việc với bất kỳ phụ thuộc nào khác không? –

26

Tìm thấy làm việc này cho tôi: http://www.php.net/manual/en/function.gzdecode.php#106397

Tùy chọn thử: 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

Đẹp, tôi đã tìm kiếm khắp nơi cho điều này – AlBeebe

+0

Dường như gzinflate không linh hoạt như gzdecode. ví dụ làm việc với gzdecode, nhưng không phải với gzinflate: http://cdn.misterwhat.com/mwuk.min.gz.css?ver=3.1 – mgutt

+0

Có, công trình này. Nó phải là câu trả lời được chấp nhận cho tôi – realtebo

0

Trước decomress dữ liệu bạn cần để lắp ráp nó. Vì vậy, nếu tiêu đề chứa

Transfer-Encoding: chunked 

bạn cần phải hủy đăng ký.

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); 
} 

nếu Content-Encoding là gzip hoặc x-gzip hoặc x-nén sử dụng gzdecode nếu Content-Encoding là deflate sử dụng gzdeflate

... 
if ($chunked) $body=http_unchunk($body); 
if ($gzip) $body=gzdecode($body); 
if ($deflate) $body=gzdeflate($body); 
... 
Các vấn đề liên quan