|
|
|
| Есть скрипт, который бетер изображение, накладывает на него водяной знак, и выдает. На сколько я понимаю (могу ошибаться) эта процедура достаточно затратная, чтобы каждый раз генерировать изображение на лету. Есть идея, как-то это закешировать. Вопрос как?
Скрипт выглядит так:
<?php
// Скрипт get_file.php
$id_file = intval(@$_GET['id_file']);
$wmark = 'watermark.png'; // Файл с водяным знаком
/*
Метод files::get_image_wmark берет изображение из БД по id_file
Накладывает на него водяной знак средсвтами GD, и выдает в браузер
*/
files::get_image_wmark($id_file, $wmark);
?>
|
Далее, если мне нужно изображение на страице, я делаю так:
<img src="get_file.php?id_file=34" />
|
И вот, хотелось бы скрипт get_file.php как-то закешировать, чтобы он постоянно одни и те же изображения не создавал снова и снова, а брались эти изображения из кэша.
С кэшами раньше никогда не работал. Прочитал пару статей на эту тему, честно говоря не очень понял.
Подскажите конкретным примером. Буду благодарен. | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 19:37)
| | а что если скажем в бд заносить флаг, что на выбранное изображение нанесен водяной знай. и при следующем обращении проверять этот флаг. если не установлен - накладываем водяной знак, иначе просто отдаем изображение
? | |
|
|
|
|
|
|
|
для: psychomc
(18.01.2011 в 20:00)
| | Дело в том, что в БД хранятся файлы БЕЗ водяных знаков. И эти файлы используются на разных проектах, и на наих в разных местах нужно накладывать разные водяные знаки. | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 20:03)
| | что если сделать флаг, уникально идентифицирующий водяной знак? или так не катит?
(может быть я не вник) | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 20:03)
| | >Дело в том, что в БД хранятся файлы БЕЗ водяных знаков. И эти файлы используются на разных
>проектах, и на наих в разных местах нужно накладывать разные водяные знаки.
Добавьте пустое поле рядом с тем, которое указывает на файлы без водяных знаков. При первом обращении, пусть скрипт создает изображение и сохраняет к нему путь в этом пустом поле. При следующих обращениях проверяйте состояние поля - если оно заполнено, берите скрипт из кэша (любая папка, куда сохраняются изображения с водяным знаком), если незаполненно, вы будете знать, что это первое обращение. | |
|
|
|
|
|
|
|
для: cheops
(18.01.2011 в 20:43)
| | Нет, я бы хотел сделать так, чтобы сгенерированная картинка хранилась в кэше у пользователя, или где-нибудь на промежуточных серверах. Т.е. чтобы когда пользователь по сайту гулял, и заходил дважды на одну и ту же страницу, чтобы ему это изображение не с сайта качалось, а бралось из его кэша, или из кэша промежуточного сервера. Примерно так.
Интересует вопрос, какие нужно послать заголовки, чтобы контент выдаваемый этим скриптом (в данном случае это сгенерированное изображение) кэшировался. | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 21:03)
| | Заставить пользователя и промежуточные сервера кэшировать данные невозможно, можно им только рекомендовать это, добавив, в META-данные время последнего обновления страницы
<META HTTP-EQUIV="Expires" CONTENT="Tue, 02 Jan 2011 01:00:00 GMT">
|
Если время не будет меняться, теоретически информация будет извлекаться из кэша (если она там есть). Но сильного эффекта я бы не ожидал. | |
|
|
|
|
|
|
|
для: cheops
(18.01.2011 в 21:16)
| | В книге "PHP5 Практика создания WEB-сайтов", на странице 147, есть пример "Управление кэшированием".
И там, пример с посылкой заголовков когда изображение берется из БД.
Если кратко, то такой (Урезан мной, набирать долго не хочется):
// Запрос к БД
$doc = mysql_query("Запрос");
// отпраялвем закголовки
header("Cach-Control: public, must-revalidate");
header("Vari: Content-ID");
header("Content-ID: ".md5(mysql_result($doc, 0, 'docs')));
header("Content-type: ".mysql_result($doc, 0, 'type'));
// Выводим картинку в окно браузера
echo mysql_result($doc, 0, 'docs');
|
Как я понял, при таких заголовках, если изображение есть в кэше (где либо) то повторный запрос к БД (обращение к этому скрипту) не происходит, изображение просто берется из кэша. Так? Но тогда, как браузер пользователя узнает что изображение обновилось, и его снова нужно запросить с сервера, если оно всегда берется из кэша? Или я че-то не так понял?
Вот хотелось бы разобраться в принципе действия данного метода кэширования. Поясните плиз. | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 21:35)
| | Да, если кэш есть в принципе - его может и не быть, только must-revalidate уберите. | |
|
|
|
|
|
|
|
для: cheops
(18.01.2011 в 21:57)
| | Поясните, плиз, как это работает? И какой от этого будет эффект, если я эти заголовки пропишу в своем скрипте? | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 21:58)
| | По сути тут один HTTP-заголовок, управления кэшем "Cach-Control: public", который всем встречным говорит - кэшируйте, если можете, нечего беспокоить изначальный сервер. | |
|
|
|
|
|
|
|
для: cheops
(18.01.2011 в 21:59)
| | А когда изображение на сервере изменится? Как об этом узнают все те, кто закешировали предыдущее изображение? | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 22:04)
| | У них стоят свои тайм-лимиты (хотя вы можете сами его рекомендовать при помощи специальных HTTP-заголовков), они обязательно перепроверят через некоторое время, можете сами тайм-лимиты выставлять, или посылать HTTP-заголовок со временем создания документа (в данном случае изображения), поменялся документ - меняйте время создания. | |
|
|
|
|
|
|
|
для: cheops
(18.01.2011 в 22:06)
| | Покажите пример, плиз.
И в моем, вышеописанном, случае, какие лучше заголовки послать? | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 22:23)
| | Можно поступить следующим образом
// Запрос к БД
$doc = mysql_query("Запрос");
// отпралявем заголовки
header("Cach-Control: public");
header("Expires: Tue, 18 Jan 2011 01:00:00 GMT");
header("Vari: Content-ID");
header("Content-ID: ".md5(mysql_result($doc, 0, 'docs')));
header("Content-type: ".mysql_result($doc, 0, 'type'));
// Выводим картинку в окно браузера
echo mysql_result($doc, 0, 'docs');
|
| |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 21:03)
| | не понятно...
если вы закешируете изображение с вотемарком у себя или на "промежуточном сервере" (который кстати тоже должен быть ваш), то картинка больше не будет генерироваться, а будет просто отдаваться как статический файл, не только для этого, но и для других пользователей, пока её не удалите.
смысл кэшировать изображение только у одного юзера, а для других по новой её генерировать?
при кэшировании на этом же сервере - у вас место на харде будет заниматься картинками в 2 раза больше, трафика будет потребляться столько же как раньше, а процессорное время и память разгрузите...
чем решение не понравилось? :)
или вам не решение надо, а просто разобраться с кэшированием на стороне клиента? :)
надеяться на то, что у клиента (причём 1-го) что-то закешируется и тем самым это разгрузит сервер - это надеяться на "авось" (имхо).... | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 20:03)
| | если скрипты разнесены отдельно по доменам, то на каждом домене создайте папку photwithwmark или типа того, если с разных доменов обращение к одним и тем же скриптам - создаёте либо папку
с началом домена что-то вроде ( str_replace('www.', '', strtolower($_SERVER['HTTP_HOST'])) . photwithwmark )
( либо можно в принципе всё в одну папку скинуть, и префикс на картинки ставить, но лучше по папкам, т.к. если будет много ф-лов в одной папке - я так не люблю :) ).
дальше выбираете имя файла
if ( file_exists( str_replace('www.', '', strtolower($_SERVER['HTTP_HOST'])) . 'photwithwmark/' . $filename ) ) {
выводите файл str_replace('www.', '', strtolower($_SERVER['HTTP_HOST'])) . 'photwithwmark/' . $filename;
} else {
накладываете водяной знак и сохраняете изображение
$fp = fopen(str_replace('www.', '', strtolower($_SERVER['HTTP_HOST'])) . 'photwithwmark/' . $filename, 'w' );
fwrite($fp, <текст изображение с вотемарком>);
fclose($fp);
}
|
ну я бы так бы сделал :)
p.s.
описал не как "Закешировать скрипт", а как закешировать ф-лы с вотемарками ... | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 19:37)
| | Где я?
Кто здесь?
Какая БД?
Вы о чем все?
tests/imgref.php
<?php
for($i = 0; $i < 10; $i++)
{ $j = $i.$i.$i.$i;
printf("<img src=img/%s.gif >%s</a><br>", $j, $j);
}
|
tests/img/.htaccess
php_value error_reporting 32767
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteBase /tests/img/
RewriteRule ^([0-9]+).gif$ /tests/imgcreator.php?id=$1 [L]
|
tests/imgcreator.php
<?php
$text = sprintf("%04d", @$_GET['id']);
$name = "img/$text.gif";
$w = 40; $h = 16;
$im = imagecreate($w, $h);
$cw = imagecolorallocate($im, 255, 255, 255);
$cb = imagecolorallocate($im, 0, 0, 0);
imagestring($im, 5, 3, 0, $text, $cb);
imagegif($im, $name);
$mt = filemtime($name);
$gmt = gmdate("r", $mt);
$l = fopen("imglog.txt", 'a+');
fputs($l, "nm=$name, gmt=$gmt\r\n");
fclose($l);
header("Last-Modified: $gmt");
header("Content-Type: image/gif");
readfile($name);
|
| |
|
|
|
|
|
|
|
для: Trianon
(18.01.2011 в 21:48)
| | Что это? Ниче не понял. Буду очень благодарен за коментарии. | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 21:53)
| | Я о том, что кешированием должен заниматься http-сервер (apache), а не php-интерпретатор.
Что если файл уже есть (уже создан php-интерпретатором в процессе обработки некоторого запроса, который был ранее), то на php вообще управление передаваться не должно. | |
|
|
|
|
|
|
|
для: Trianon
(18.01.2011 в 22:00)
| | >Я о том, что кешированием должен заниматься http-сервер (apache), а не php-интерпретатор.
>Что если файл уже есть (уже создан php-интерпретатором в процессе обработки некоторого запроса, который был ранее), то на php вообще управление передаваться не должно.
И я примерно так думаю. Вопрос в том, как это реализовать в моем, вышеописанном, случае? | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 22:06)
| | я привел пример.
imgref.php порождает страницу с несколькими картинками.
по запросу картинки apache либо берет уже построенную ранее картинку, либо по условию отсутствия файла через Mod Rewrite сваливается в скрипт imgcreator.php с требованием создать файл с картинкой и выбросить его содержимое в поток браузеру, предварив причитающимися заголовками. | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 22:06)
| | Я вообще считаю, что хранить изображения в базе - извращение. Если нужно иметь несколько вариантов водяных знаков, нужно создать несколько папок в которые складывать рисунки уже с нужными водяными знаками (при загрузке изображения сразу обрабатываются, получая несколько нужных копий).
Вопрос о том, как их кешировать отпадает сам собой. Ведь даже анализ того, есть ли файл и какова его дата - это уже некоторая нагрузка на сервер. А так - файлы заранее созданы. Просто бери и передавай их браузеру | |
|
|
|
|
|
|
|
для: tAleks
(18.01.2011 в 19:37)
| | Сказать честно прочитал только вопрос, понял одно -нужно кешировать изображение....
вот тема, я сделал через htaccess и работает отлично.
http://softtime.ru/forum/read.php?id_forum=2&id_theme=75115&page=1 | |
|
|
|