質問

今、 mod_gzip または mod_deflate を有効にできないサーバーからCSSおよびJSファイルを提供しようとしています。そこで、GZIPで圧縮してユーザーに戻るための小さなPHPスクリプトを作成しました。

サンプルコード:

$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();

今、2つの問題があります。 1つは、圧縮ファイルの結果のサイズを判断して、ブラウザにコンテンツの長さを知らせるのに問題があることです。通常、次の行を含めます。

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

しかし、私がそうするなら、さらなるデータを待っている間にブラウザがハングします。合計サイズを計算する方法はありますか?または、このヘッダーディレクティブを無視する必要があります。

もう1つの問題は、FirefoxでこのPHPファイルを表示するたびに、結果をダウンロードさせようとすることです。 Chromeでは、期待どおりに表示されます。提案はありますか?

編集: SoapBoxのおかげで、コードの末尾を次のように置き換えました:

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(

今、 mod_gzip または mod_deflate を有効にできないサーバーからCSSおよびJSファイルを提供しようとしています。そこで、GZIPで圧縮してユーザーに戻るための小さなPHPスクリプトを作成しました。

サンプルコード:

$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();

今、2つの問題があります。 1つは、圧縮ファイルの結果のサイズを判断して、ブラウザにコンテンツの長さを知らせるのに問題があることです。通常、次の行を含めます。

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

しかし、私がそうするなら、さらなるデータを待っている間にブラウザがハングします。合計サイズを計算する方法はありますか?または、このヘッダーディレクティブを無視する必要があります。

もう1つの問題は、FirefoxでこのPHPファイルを表示するたびに、結果をダウンロードさせようとすることです。 Chromeでは、期待どおりに表示されます。提案はありますか?

編集: SoapBoxのおかげで、コードの末尾を次のように置き換えました:

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

これは、コンテンツの長さに最適です!しかし、Firefoxにファイルを表示する代わりにダウンロードさせるようにしています。 :(

再編集: Cletusの好意により修正されたコードの終わりのコードです。

<*>

Firefoxがファイルをダウンロードしようとし続ける理由を理解するために、新しい質問を始めます。

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がファイルをダウンロードしようとし続ける理由を理解するために、新しい質問を始めます。

役に立ちましたか?

解決

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

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エンコーディングの問題を自分で処理するよりもずっと優れています。

他のヒント

最初にgzip全体を実行し、結果を測定する必要があります(メモリにコンテンツを保持するか、圧縮してディスクに書き込み、gzip圧縮されたファイルをstat's)、次にContent-Lengthヘッダーを書き込んでから、ファイルの内容を送信します。

またはチャンク転送エンコードを使用します。

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

コンテンツの長さについては、この値をそのままにしておくか、「Transfer-Encoding:chunked」を使用する方法を見つけてください。 (このヘッダーをjsut送信することはできません。特別にデータをフォーマットする必要があります)。 ob_end_flush が自動的にチャンクを有効にする可能性があります。

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top