Подтвердить что ты не робот

File_get_contents или readfile для отображения образа файловой системы

Может ли кто-нибудь посоветовать, какая лучшая функция PHP для отображения изображения, хранящегося в файловой системе, - file_get_contents или readfile. Мы переключаемся с отображения изображений, хранящихся в базе данных, поэтому нам все равно нужно вызывать изображения через файл PHP и не может напрямую ссылаться на файловую систему. Я видел людей, рекомендующих обе функции, но я склонен к использованию readfile. Поблагодарили бы за любой ввод.

4b9b3361

Ответ 1

Если вам не нужно манипулировать изображениями (изменение размера, добавление водяных знаков,...) readfile() будет лучшим выбором так как он записывает файл непосредственно в выходной буфер. file_get_contents() будет читать файл в памяти вместо этого - требуется много памяти с большими файлами.

Ответ 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- Поскольку подход будет лучше подходит для большинства приложений, обслуживающих файлы.

Ответ 3

Я бы сделал что-то вроде:

header('Content-type: image/jpeg');
readfile('something.jpg');

readfile() кажется более полезным для этой цели, когда он читает файл и записывает его в выходной буфер, возвращая количество прочитанных байтов из файла или false при ошибке.

Ответ 4

Я должен использовать fpassthru Используя fopen, вы можете обрабатывать ошибки более точно.

PS: убедитесь, что ваш прямой вывод из файловой системы не уязвим!

Ответ 5

file_get_contents() является предпочтительным способом чтения содержимого файла в строку. Он будет использовать методы сопоставления памяти, если их поддерживает ваша ОС для повышения производительности. Но в стороне, я не знаю, что лучше. Вы можете попытаться увидеть, обладает ли огромный файл более высокой производительностью с помощью file_get_contents(), но я ожидаю, что сетевой трафик будет гораздо более серьезной проблемой, чем сервер файл-IO. и readfile() используется для загрузки файла, передав content-type в header().