gzip通信を有効にしてWebページのフェッチを行うと、帯域や通信量が節約できるだけでなく、回線次第では応答速度も速まります。
PHPであればどの環境でも基本的に使えるfile_get_contents
関数を用いて、gzip通信を行うサンプルを紹介します。
まず、file_get_contentsと併用してgzipをデコードする実装は大きく分けて2つあります。
- PHP 5.4 からはgzdecode関数が使える
- PHP 5.4 未満は次のような実装を自前で用意する必要がある
// その1
if(!function_exists("gzdecode"))
{
function gzdecode($data){
return gzinflate(substr($data, 10, -8));
}
}
// その2
function gzDecodeWithTmpFile($data)
{
$gzfile = tempnam('/tmp','gzdecode');
file_put_contents($gzfile, $data);
ob_start();
readgzfile($gzfile);
$result = ob_get_clean();
return $result;
}
実装サンプル
先ほどの例を踏まえて、PHP5系のバージョン差異を吸収できる実装サンプルは次の通りです。
<?php
class GzipHttpRequest
{
static public function fetchUrl($url)
{
$context = self::getStreamContext();
$content = file_get_contents($url, false, $context);
if (self::isGzipResponse($http_response_header)) {
return self::gzdecode($content);
} else {
return $content;
}
}
static private function getStreamContext()
{
$opts = array(
'method' => "GET",
'header' => implode("\r\n", array('Accept-Encoding: gzip,deflate'))
);
return stream_context_create(array('http' => $opts));
}
static private function isGzipResponse($headers)
{
foreach($headers as $header) {
if (stristr($header, 'content-encoding') and stristr($header, 'gzip')) {
return true;
}
}
}
static private function gzdecode($data)
{
if(function_exists("gzdecode")) {
return gzdecode($data);
} else {
return gzinflate(substr($data, 10, -8));
// 一時ファイルを書き出してデコードする手法もあります
//return self::gzDecodeWithTmpFile($data);
}
}
static private function gzDecodeWithTmpFile($data)
{
$gzfile = tempnam(sys_get_temp_dir(), 'gzdecode');
file_put_contents($gzfile, $data);
ob_start();
readgzfile($gzfile);
$result = ob_get_clean();
return $result;
}
}
$url = "http://www.yahoo.co.jp/";
echo GzipHttpRequest::fetchUrl($url);
curlを使う場合
PHPがcURLサポート付きでコンパイルされており、なおかつcurl 7.10以降を利用している場合には、次のオプションも便利です。
curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
ref. http://php.net/manual/ja/function.curl-setopt.php
参考サイト
-
PHP file_get_contents giving garbled output
http://digitalpbk.com/php/file_get_contents-garbled-gzip-encoding-website-scraping -
Php – Fetch gzipped content over http with file_get_contents
http://www.binarytides.com/php-fetch-gzipped-content-over-http-with-file_get_contents/