13

?img=パラメータで呼び出される PHP スクリプトがあります。

そのパラメーターの値は、画像の (urlencoded) URL です。

私のスクリプトは、その画像がサーバーに既に保存されているかどうかを確認します。

そうでない場合は、ダウンロードします。その後、必要に応じて画像のサイズを変更し、STDOUT に送信します。つまり、リクエストしているブラウザーに送り返し、Content-TypeヘッダーとLast-modifiedヘッダーを先頭に追加します。

Connection:close
Content-Type:image/jpeg
Date:Fri, 01 Jun 2012 08:28:30 GMT
Last-Modified:Fri, 01 Jun 2012 08:02:44 GMT
Server:Apache/2.2.15 (CentOS)
Transfer-Encoding:chunked
X-Powered-By:PHP/5.3.3

これは、いくつかのクロスドメインの問題を回避するために必要であり、1 年以上にわたってうまく機能しています。

スクリーンショット

ただし、着信するIf-Modified-sinceヘッダーを処理する機能を追加したいと思います。つまり、 Not Modified 304応答を送信します。

私の質問は次のとおりです。

1)Apacheで実行すると、PHPでも可能ですか?

2) ここで PHP で最適な日付を処理 (つまり、解析して生成) する方法は?

おまけの質問)サイズ変更された画像にContent-Lengthヘッダーを追加するにはどうすればよいですか?

私のコードは以下のとおりです (CURL のダウンロード部分は省略しています)。

<?php

define('CACHE_DIR', '/var/www/cached_avatars/');

$img    = urldecode($_GET['img']);
$cached = CACHE_DIR . md5($img);

# omitted downloading part for brevity

$readfh = fopen($cached, 'rb');
if ($readfh) {
        flock($readfh, LOCK_SH);

        $size = getimagesize($cached);
        $w    = $size[0];
        $h    = $size[1];
        $type = $size[2];
        $mime = $size['mime'];

        # find the downscale factor to fit image into $maxw x $maxh
        $scale = max($w / $maxw, $h / $maxh);

        header('Content-Type: ' . $size['mime']);
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s T', filemtime($cached)));

        $length = filesize($cached);
        $buf = fread($readfh, $length);
        fclose($readfh);

        # the image is smaller than $maxw x $maxh, do not scale up
        if ($scale <= 1) {
                header('Content-Length: ' . $length);
                print($buf);
                return;
        }

        $tw = $w / $scale;
        $th = $h / $scale;
        $image = imagecreatefromstring($buf);
        $thumb = imagecreatetruecolor($tw, $th);
        imagecopyresampled($thumb, $image, 0, 0, 0, 0, $tw, $th, $w, $h);
        imagedestroy($image);

        # How to add Content-Length here, after image resizing?

        if (IMAGETYPE_JPEG == $type)
                imagejpeg($thumb, null, 75);
        else if (IMAGETYPE_PNG == $type)
                imagepng($thumb, null, 9);
        else if (IMAGETYPE_GIF == $type)
                imagegif($thumb, null);

        imagedestroy($thumb);
}

?>
4

2 に答える 2

40

これはPHPで間違いなく可能です!

ブラウザーは、変更があったかどうかを確認するときに、If-Modified-Sinceヘッダーを送信します。PHP では、この値は 内に設定され$_SERVER['HTTP_IF_MODIFIED_SINCE']ます。

日付/時刻の値 (rfc822 を使用してエンコードされていると思います) をデコードするには、次strtotime()のように使用できます。

if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && 
    strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= filemtime($localFileName))
{
    header('HTTP/1.0 304 Not Modified');
    exit;
}

説明:If-Modified-Sinceヘッダーがブラウザーによって送信され、日付/時刻が少なくとも提供しているファイルの変更日である場合は、"304 Not Modified" ヘッダーを記述して停止します。

それ以外の場合、スクリプトは通常どおり続行されます。

于 2012-06-01T08:55:26.107 に答える