Каким будет наилучший способ обработки кэширования изображений с помощью PHP.
Имя файла в настоящее время хранится в базе данных MySQL, которая переименовывается в GUID при загрузке вместе с исходным именем файла и тегом alt.
Когда изображение помещается на страницы HTML, это делается с использованием URL-адреса, например «/images/get/200×200/{guid}.jpg», который переписывается в php-скрипт. Это позволяет моим дизайнерам указывать (грубо – исходное изображение может быть меньше) размер файла.
Затем скрипт php создает хэш размера (200×200 в url) и имя файла GUID, и если файл был сгенерирован раньше (файл с именем хэша существует в каталоге TMP) отправляет файл из каталога приложения TMP. Если хэшированное имя файла не существует, оно создается, записывается на диск и подается таким же образом,
Насколько это эффективно? (Он также поддерживает водяные знаки изображений, а настройки водяного знака также хранятся в хэше, но это не подходит для этого.)
Существует два опечатка в примере перезаписи Дана Удей (и я не могу прокомментировать его), это скорее должно быть:
RewriteCond %{REQUEST_URI} ^/images/cached/ RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f RewriteRule (.*) /images/generate.php?$1 [L]
С уважением.
Я бы сделал это по-другому.
Проблемы: 1. Наличие PHP для работы с файлами менее эффективно, чем могло бы быть. 2. PHP должен проверять наличие файлов каждый раз, когда изображение запрашивается. 3. Apache намного лучше, чем PHP.
Здесь есть несколько решений.
Вы можете использовать mod_rewrite
на Apache. Можно использовать mod_rewrite для тестирования, чтобы увидеть, существует ли файл, и если да, то вместо этого используйте этот файл. Это полностью исключает PHP и делает вещи намного быстрее. Однако реальный способ сделать это должен был бы создать определенную схему URL, которая должна всегда существовать, а затем перенаправить на PHP, если нет.
Например:
RewriteCond %{REQUEST_URI} ^/images/cached/ RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f RewriteRule (.*) /images/generate.php?$1 [L]
Поэтому, если клиент запрашивает /images/cached/<something>
и этот файл уже не существует, Apache перенаправляет запрос на /images/generate.php?/images/cached/<something>
. Этот скрипт может затем сгенерировать изображение, записать его в кэш и затем отправить его клиенту. В будущем сценарий PHP никогда не вызывается, кроме новых изображений.
Используйте кеширование. Как сказал другой плакат, используйте такие вещи, как mod_expires
, Last-Modified headers и т. Д., Чтобы отвечать на условные запросы GET. Если клиенту не требуется повторно запрашивать изображения, загрузка страниц будет резко увеличиваться, а загрузка на сервере будет уменьшаться.
Для случаев, когда вам нужно отправить изображение с PHP, вы можете использовать mod_xsendfile
для этого с меньшими накладными расходами. См. Превосходное сообщение в блоге от Арнольда Дэниелса по этой проблеме, но обратите внимание, что его пример для загрузки. Для обслуживания встроенных изображений выньте заголовок Content-Disposition (третий вызов header ()).
Надеюсь, что это поможет – больше после того, как моя мигрень прояснится.
Одно примечание стоит добавить, чтобы убедиться, что вы код не генерирует «несанкционированные» размеры этих изображений.
Таким образом, следующий URL-адрес создаст версию 1234 с разрешением 200×200, если ее еще не существует. Я настоятельно рекомендую вам убедиться, что запрашиваемый URL-адрес содержит размеры изображений, которые вы поддерживаете.
/images/get/200x200/1234.jpg
Злоумышленник может начать запрашивать случайные URL-адреса, всегда изменяя высоту и ширину изображения. Это вызовет у вашего сервера некоторые серьезные проблемы, так как он сидит там, по сути, под атакой, генерируя изображения размеров, которые вы не поддерживаете.
/images/get/0x1/1234.jpg /images/get/0x2/1234.jpg ... /images/get/0x9999999/1234.jpg /images/get/1x1/1234.jpg ... etc
Вот случайный снимок кода, иллюстрирующий это:
<?php $pathOnDisk = getImageDiskPath($_SERVER['REQUEST_URI']); if(file_exists($pathOnDisk)) { // send header with image mime type echo file_get_contents($pathOnDisk); exit; } else { $matches = array(); $ok = preg_match( '/\/images\/get\/(\d+)x(\d+)\/(\w+)\.jpg/', $_SERVER['REQUEST_URI'], $matches); if(! $ok) { // invalid url handleInvalidRequest(); } else { list(, $width, $height, $guid) = $matches; // you should do this! if(isSupportedSize($width, $height)) { // size is supported. all good // generate the resized image, save it & output it } else { // invalid size requested!!! handleInvalidRequest(); } } } // snip function handleInvalidRequest() { // do something w/ invalid request // show a default graphic, log it etc } ?>
Кажется большой пост, но моя проблема все еще остается нерешенной. У меня нет доступа к htaccess в моем хост-провайдере, поэтому нет вопроса об настройке apache. Есть ли способ установить заголовок cce-control для изображений?
Ваш подход кажется вполне разумным – я бы добавил, что должен быть установлен какой-то механизм, чтобы проверить, была ли дата создания кешированной версии, после последней измененной метки времени исходного (исходного) файла изображения и, если не регенерировать кешированную / измененную версию , Это гарантирует, что если изображение будет изменено дизайнерами, кэш будет обновлен соответствующим образом.
Это звучит как надежный способ сделать это. Следующим шагом может стать выход за пределы PHP / MySQL.
Возможно, настройте заголовки :
Если вы используете PHP для отправки типов MIME, вы также можете использовать заголовки «Keep-alive» и «Cache-control», чтобы продлить срок службы ваших изображений на сервере и снять некоторую нагрузку на PHP / MySQL.
Кроме того, рассмотрите плагин apache для кеширования. Как mod_expires .
О, еще одна вещь, сколько у вас контроля над вашим сервером? Должны ли мы ограничивать этот разговор только PHP / MySQL?
Мне удалось сделать это, просто используя заголовок redirect в PHP:
if (!file_exists($filename)) { // *** Insert code that generates image *** // Content type header('Content-type: image/jpeg'); // Output readfile($filename); } else { // Redirect $host = $_SERVER['HTTP_HOST']; $uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\'); $extra = $filename; header("Location: http://$host$uri/$extra"); }
Вместо сохранения адреса файла в db я предпочитаю добавлять случайное число к имени файла всякий раз, когда пользователь входит в систему. Что-то вроде этого для пользователя 1234: image / picture_1234.png? Rnd = 6534122341
Если пользователь отправляет новое изображение во время сеанса, я просто обновляю случайное число.
GUID решает проблему кеша 100%. Однако это делает сложнее отслеживать файлы изображений. Благодаря этому методу пользователь может увидеть то же изображение снова при следующем входе в систему. Однако шансы низкие, если вы производите свое случайное число из миллиарда чисел.
phpThumb – это среда, которая генерирует измененные изображения / эскизы на лету. Он также реализует кеширование, и его очень легко реализовать.
Код для изменения размера изображения:
<img src="/phpThumb.php?src=/path/to/image.jpg&w=200&h=200" alt="thumbnail"/>
даст вам миниатюру 200 x 200;
Он также поддерживает водяные знаки.
Проверьте это: http://phpthumb.sourceforge.net/