У меня есть PHP-скрипт, который вызывается с параметром ? Img = .
Значение для этого параметра – URL (urlencoded) изображения.
Мой скрипт проверяет, сохраняется ли это изображение на моем сервере.
Если нет – он загружает его. После этого он необязательно изменяет размер изображения и отправляет его в 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
Это необходимо для решения некоторых проблем Flash / Crossdomain.xml и хорошо работает для меня с года:
Однако я хотел бы добавить функциональность для обработки входящего заголовка If-Modified-since – для отправки ответа Not Notified 304 .
Мои вопросы:
1) Возможно ли это в PHP, когда вы запускаете Apache?
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 MYH: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); } ?>
Я не прошу, чтобы кто-то выполнял мою работу за меня, просто просил о хороших указателях или фрагментах кода, поскольку у меня еще нет опыта в этих областях (заголовки + даты) PHP.
Это определенно возможно в 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» и останавливаетесь.
В противном случае сценарий продолжается как обычно.
Недавно мне пришлось использовать эту функцию (показ изображения через PHP), чтобы сделать изображения видимыми только для зарегистрированных пользователей. Код Джека был полезен, но мне пришлось сделать несколько хаков, чтобы он работал отлично. Думал, я должен поделиться этим.
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); }
Короче говоря, скрипт возвращает Not Modified, если это запрос браузера HTTP_IF_MODIFIED_SINCE
. В противном случае изображение подается с соответствующими заголовками и датами истечения срока действия.