Может ли кто-нибудь посоветовать, какая лучшая функция PHP для отображения изображения, хранящегося в файловой системе, - file_get_contents
или readfile
. Мы переключаемся с отображения изображений, хранящихся в базе данных, поэтому нам все равно нужно вызывать изображения через файл PHP и не может напрямую ссылаться на файловую систему. Я видел людей, рекомендующих обе функции, но я склонен к использованию readfile
. Поблагодарили бы за любой ввод.
Ответ 2
Обязательно используйте кеширование при написании сценариев, подобных этому!
Веб-сервер, обслуживающий статическое изображение, будет вести переговоры с клиентом, когда изображение будет повторно запрошено при следующем посещении страницы, и если сервер определит, что кешированная копия изображения на стороне клиента все еще действительна, изображение не будет повторно передан.
Так как наивный script не выполняет этого согласования, изображение будет повторно передано клиенту на каждом запросе страницы, что будет стоить вам гораздо больше полосы пропускания, чем необходимо.
Для этого существует три механизма. Я не могу точно сказать, как написать оптимальный script, поскольку мне никогда не приходилось делать это раньше, и я не уверен, как разные заголовки кеширования взаимодействуют и на какой версии HTTP, но я призываю вас исследовать в дальнейшем.
Три механизма, о которых я знаю:
Истекает (HTTP/1.0)
Самый простой. Этот заголовок сообщает клиенту, что изображение определенно будет действительным до заданного момента времени. Клиент даже не выполнит запрос к script до тех пор, пока это время не пройдет, поэтому установка этого параметра может сэкономить вам (некоторые) циклы процессора на сервере и задержку загрузки изображений в вашем веб-приложении.
Как вы должны установить это, полностью зависит ваше приложение; Ваши изображения меняются быстро или редко? Если изображение изменяется до истечения времени, которое вы отправили клиенту, клиент не увидит новое изображение.
Пример:
header("Expires: " . gmdate('D, d-M-Y H:i:s \G\M\T', time() + 60)); // Valid for a minute
(Примечание. Истекает, по-видимому, заменено Cache-Control в HTTP/1.1)
If-Modified-Since (HTTP/1.1)
Клиент HTTP/1.1 может отправить этот заголовок, если у него уже есть копия изображения, и отмечает, в какое время копируется дата. Затем вы можете определить в своей базе данных, если текущая версия изображения была изменена раньше или позже. Если версия клиента по-прежнему правильная, просто отправьте ответ "304 Not Modified" и завершите работу (тем самым не допуская передачу изображения).
Пример:
$cache_time = parse_browsers_date_time_format($_SERVER["IF-MODIFIED-SINCE"]);
$actual_time = get_current_resource_time_from_db();
if ($actual_time <= $cache_time) {
header("HTTP/1.1 304 Not Modified");
die;
}
// ... Produce and output resource here
(Примечание: клиенты могут отправлять только If-Modified-Since, если вы также отправляете Last-Modified в исходном ответе. Я не уверен в этом, исследование для себя.)
ETag/If-None-Match (HTTP/1.1)
Этот метод похож на согласование If-Modified-Since, но вместо него он использует хэш изображения, чтобы узнать, изменилось ли содержимое. Он работает следующим образом: сервер вычисляет некоторый хэш для изображения и отправляет этот хеш при первом запросе изображения в заголовке ETag.
В последующих запросах сервер отправит хэш обратно в поле запроса If-None-Match. Если хеш клиента совпадает с текущим хешем изображения, изображение не было изменено между ними, а script может быть достаточно, просто отправив "304 Not Modified".
Поскольку ETags, по-видимому, на самом деле предназначены для предотвращения проблем concurrency в клиентских запросах с побочными эффектами (то есть POST и PUT), и потому что вычисление хэша является дорогостоящей операцией, я думаю, что If-Modified- Поскольку подход будет лучше подходит для большинства приложений, обслуживающих файлы.