2011-04-18 79 views
11

我用Page Speed測試了我的網站,結果大約70/100。啓用壓縮是降低速度的第一個也是最重要的因素。PHP手冊GZip編碼

我知道我能做到這一點通過修改php.ini中自動做到這一點,但我更感興趣的是手動方法(gzencode)。

的問題是要麼所有的瀏覽器中打開的網站(Firefox的失敗:「您要查看的頁面無法顯示,因爲它使用的壓縮無效或不支持的形式」,鍍鉻:「303,ERR內容編碼「等)或他們顯示編碼的字符串。

活頭顯示,瀏覽器接受編碼,並且響應具有內容類型集,但它仍然失敗。

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

如果我改變內容編碼爲zlib,我得到的編碼字符串:

‹������Õ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 

我真的不關心了有關獲取壓縮不亞於我想知道爲什麼它不工作。

乾杯,

+0

+1有趣的問題 – Wh1T3h4Ck5 2011-04-18 06:06:04

+0

如果'$ supportsGzip'不應'內容Length'是gzip壓縮內容的長度呢? – Fanis 2011-04-18 06:18:18

+0

@Fanis,內容包含緩衝區的內容,無論是編碼還是平原,取決於$ supportsGzip。 – 2011-04-18 06:51:37

回答

10

嗯,我想這是因爲你試圖壓縮一個空字符串。

我把你的腳本,你給它,並在FF和IE瀏覽器運行它。

兩個都失敗了,FF說有問題(就像你說的)。

但是,我發現$ data是一個空字符串。

當我在文件頂部設置$data = "Some test data.";它立即工作(瀏覽器顯示「一些測試數據」),並檢查Firebug,我可以看到正確的標題。

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

編輯:另外,只是想指出,你if ($supportsGzip) {有點奇怪,因爲你else條件實際上應該回聲出$data,不$content

編輯:好的,根據您上面修改的功能,有兩個關鍵問題。

的主要問題有,你通過調用ob_end_clean()擦你的頭的事實做。關於PHP Docs的評論指出「ob_end_clean()放棄標題」。

這意味着你叫ob_end_clean()會得到消滅之前設置的任何頭。此外,您的修改函數也不會發送gzip編碼標頭。

我必須說,有可能是沒有必要甚至在這裏使用ob_start和相關的功能,無論是。請嘗試以下操作:

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

這在IE和FF,但我沒有時間來測試其他瀏覽器。

如果你真的必須使用ob_start和相關的功能,確保你設定標題調用ob_end_clean()後。

+0

GZIP不是加密算法,而是壓縮算法。 – Gumbo 2011-04-18 10:47:35

+0

@Gumbo Doh,對不起,大腦不正確。固定。 – 2011-04-18 10:48:59

+0

數據字符串是一個函數參數,代碼是一個片段。 我什至嘗試'數據=「一些字符串」,仍然沒有通過測試。 – 2011-04-19 05:18:07

6

我建議使用http://php.net/manual/de/function.ob-gzhandler.php,這個作品開箱我:

在我的index.php我只是一些輸出之前放置此:

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

而且它編碼吧!

+1

'如果($ supportsGzip){ ob_start( 「ob_gzhandler」); echo trim(preg_replace('/ \ s + /','',$ data)); }' 嘗試,但仍然不會打開。在調用此函數之前沒有顯示輸出。 – 2011-04-19 05:24:58

+0

你不需要的,如果()在它的前面,因爲你的PHP檢查(從文檔):ob_gzhandler()的目的是作爲一個回調函數ob_start(),以幫助促進發送GZ-編碼數據到支持壓縮網頁的網頁瀏覽器。在ob_gzhandler()實際發送壓縮數據之前,它會確定瀏覽器編碼的內容類型(「gzip」,「deflate」或根本沒有),並將相應地返回其輸出。 ...如果瀏覽器不支持壓縮頁面,此函數返回FALSE。 – daschl 2011-04-19 06:10:01

+0

有一種方法可以檢查用戶是否支持編碼以下代碼應該位於文檔的開頭: if(substr_count($ _ SERVER ['HTTP_ACCEPT_ENCODING'],'gzip'))ob_start(「ob_gzhandler」); else ob_start(); 沒有必要使用ob_flush(在這種情況下會自動添加) – Zydnar 2016-11-20 10:36:37

0

有幾件事情:

  1. 你可能要添加另一個標題: 標題( '內容編碼:gzip');

  2. 您正在使用ob_end_clean,這不刪除其發送給瀏覽器的所有呼應/印刷內容。取決於你想要做什麼,你可能需要使用ob_flush。

  3. 要確保你的輸出緩衝和處理(如果你使用PHP的輸出緩衝壓縮壓縮),確保所有回聲/打印語句放在ob_start和使用ob_flush sttements之間。

--and然後再次嘗試:)