2009-05-03 7 views
13

今私はmod_gzipまたはmod_deflateを有効にしないサーバーからCSSとJSファイルを提供しようとしています。だから私はGZIPで圧縮してユーザーに返す小さなPHPスクリプトを書いた。gzippedファイルのContent-Lengthを調べる方法は?

コード例:私は今、二つの問題を抱えている

$filename = "style.css"; 

if (!file_exists($filename) || !($info = stat($filename))) { 
    header("HTTP/1.1 404 Not Found"); 
    die(); 
} 

header("Date: ".gmdate("D, j M Y H:i:s e", time())); 
header("Cache-Control: max-age=2592000"); 
header("Last-Modified: ".gmdate("D, j M Y H:i:s e", $info['mtime'])); 
header("Etag: ".sprintf("\"%x-%x-%x\"", $info['ino'], $info['size'], $info['mtime'])); 
header("Accept-Ranges: bytes"); 
header("Cache-Control: Expires ".gmdate("D, j M Y H:i:s e", $info['mtime']+2592000)); 
header("Content-Type: text/html"); 

ob_start("ob_gzhandler"); 
echo file_get_contents($filename); 
ob_end_flush(); 

。最初は、ブラウザにコンテンツの長さを知らせるために圧縮ファイルのサイズを決めるのに問題があります。私がしなければ、より多くのデータを待つようにしようとしているときに、ブラウザがハングアップし、

header("Content-Length: ".$info["size"]); 

しかし:通常、私はこの行が含まれます。合計サイズを計算する方法はありますか?または、このヘッダー指示を無視する必要があります。

もう1つの問題は、FirefoxでこのPHPファイルを表示するたびに、私に結果をダウンロードさせようとすることです。 Chromeでは、予想通りに表示されます。助言がありますか?

編集:演説におかげで、私はこれで、コードの末尾に置き換え:

header("Content-Encoding: gzip"); 
$compressed = gzencode(file_get_contents($filename), 5); 
header("Content-Length: ".strlen($compressed)); 
die($compressed); 

これは、コンテンツの長さのための素晴らしい作品!しかし、私はまだそれを表示するのではなく、Firefoxにファイルをダウンロードさせています。 :(再び

編集:ここでははCletusの礼儀、修正エンド・オブ・コードのコードです

// Start buffered output 
ob_start(); 
// Check for gzip capability 
if (stripos($_SERVER['HTTP_ACCEPT_ENCODING'], "gzip") !== false) { 
    ob_start("ob_gzhandler"); 
    echo file_get_contents($filename); 
    ob_end_flush(); 
} else 
    echo file_get_contents($filename); 

// Write the content length 
header('Content-Length: '.ob_get_length()); 
ob_end_flush(); 

私はFirefoxをしようとし続ける理由を把握するために新しい質問を開始するつもりです。

+0

回答に記載されているヘッダーのいくつかにはいくつかの誤りがあります。二重Cache-Control、Cache-Control:Expires ....の行はExpiresでなければなりません:...そしてEtagはETagでなければなりません。 –

答えて

18

コンテンツの長さを知るには、クライアントがgzipエンコーディングをサポートしているかどうかを知る必要があり、ob_gzhandlerを使用してその決定を委任したことになります。HTTP Headersから:

ob_start(); 
ob_start('ob_gzhandler'); 

    ... output the page content... 

ob_end_flush(); // The ob_gzhandler one 

header('Content-Length: '.ob_get_length()); 

ob_end_flush(); // The main one 

完全版:

$filename = "style.css"; 

if (!file_exists($filename) || !($info = stat($filename))) { 
    header("HTTP/1.1 404 Not Found"); 
    die(); 
} 

header("Date: ".gmdate("D, j M Y H:i:s e", time())); 
header("Cache-Control: max-age=2592000"); 
header("Last-Modified: ".gmdate("D, j M Y H:i:s e", $info['mtime'])); 
header("ETag: ".sprintf("\"%x-%x-%x\"", $info['ino'], $info['size'], $info['mtime'])); 
header("Accept-Ranges: bytes"); 
header("Expires: ".gmdate("D, j M Y H:i:s e", $info['mtime']+2592000)); 
header("Content-Type: text/css"); // note: this was text/html for some reason? 

ob_start(); 
ob_start("ob_gzhandler"); 
echo file_get_contents($filename); 
ob_end_flush(); 
header('Content-Length: '.ob_get_length()); 
ob_end_flush(); 

これは、GZIPエンコーディングの問題に自分自身を取るよりもはるかに良いです。

1

まず、gzip全体を実行し、結果を測定する必要があります(メモリ内の内容を保持するか、圧縮してからgzip形式のファイルをstat'ingしてディスクに書き込むか) -Lengthヘッダーを入力し、ファイルの内容を送信します。

またはchunked transfer encodingを使用してください。

+0

関数 'file_put_contents'が機能します。 – hyip

1

Firefoxの問題を解決するには、ブラウザがコンテンツの解凍を知るように、header("Content-Encoding: gzip");を含める必要があると思います。

コンテンツの長さについては、この値をそのままにするか、 "Transfer-Encoding:chunked"を使用する方法を見つけようとします(このヘッダーを送信することはできません。特別なデータ)。 ob_end_flushは自動的にチャンクを有効にすることができます。

wiresharkを取得し、PHPスクリプトが送信しているものをキャプチャして、正しく動作しているサーバと比較して、欠落しているヘッダなどを確認することをお勧めします。

+0

実際には、クライアントがサポートしている場合、ob_start( "ob_gzhandler")は何をしますか。 – cletus

関連する問題