Ale*_*ber 12 php if-modified-since
我有一个PHP脚本,使用?img =参数调用.
该参数的值是图像的(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
Run Code Online (Sandbox Code Playgroud)
这需要解决一些跨域问题,并且在一年多的时间内对我有用:
但是,我想添加处理传入的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);
}
?>
Run Code Online (Sandbox Code Playgroud)
Ja͢*_*͢ck 36
这在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;
}
Run Code Online (Sandbox Code Playgroud)
说明:如果If-Modified-Since浏览器发送标题并且日期/时间至少是您正在服务的文件的修改日期,则编写"304 Not Modified"标题并停止.
否则,脚本将按正常方式继续.
我最近不得不使用此功能(通过 PHP 提供图像)以使图像仅对注册用户可见。Jack 的代码很有帮助,但我必须做一些技巧才能让它完美运行。想我应该分享这个。
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= filemtime($path_to_image))
{
header('HTTP/1.0 304 Not Modified');
header("Cache-Control: max-age=12096000, public");
header("Expires: Sat, 26 Jul 2015 05:00:00 GMT");
header("Pragma: cache");
exit;
}else{
header("Content-type: image/jpeg");
header("Cache-Control: max-age=12096000, public");
header("Expires: Sat, 26 Jul 2015 05:00:00 GMT");
header("Pragma: cache");
echo file_get_contents($path_to_image);
}
Run Code Online (Sandbox Code Playgroud)
简而言之,如果是浏览器请求,脚本将返回 Not Modified HTTP_IF_MODIFIED_SINCE。否则,图像会带有适当的标题和到期日期。