Подавать изображение с помощью скрипта PHP и напрямую загружать изображение

Я хочу отслеживать, как часто загружаются некоторые внешние изображения. Поэтому моя идея заключается не в том, чтобы дать uri прямо так:

www.site.com/image1.jpg 

Я могу создать PHP-скрипт, который читает изображение, поэтому я создал PHP-файл, и мой HTML-код будет выглядеть так:

 <img src="www.site.com/serveImage.php?img=image1.jpg"> 

но я не знаю, как читать изображение с диска и возвращать его. Будет ли я возвращать массив байтов или задавать тип содержимого?

С уважением, Мишель

Solutions Collecting From Web of "Подавать изображение с помощью скрипта PHP и напрямую загружать изображение"

Вы должны установить тип содержимого:

 header("Content-type: image/jpeg"); 

Затем вы загружаете изображение и выводите его следующим образом:

 $image=imagecreatefromjpeg($_GET['img']); imagejpeg($image); 

Отправка изображений через скрипт хороша для других вещей, таких как изменение размера и кэширование по требованию.

Как ответил Паскаль МАРТИН, функция readfile и эти заголовки являются требованиями:

  • Тип содержимого
    • Тип mime этого содержимого
    • Пример: header('Content-Type: image/gif');
    • См. Функцию mime_content_type
    • Типы
      • image/gif
      • image/jpeg
      • image/png

Но помимо очевидного типа контента вы также должны посмотреть на другие заголовки, такие как:

  • Content-Length
    • Длина тела ответа в октетах (8-разрядные байты)
    • Пример: header('Content-Length: 348');
    • См. Функцию filesize
    • Позволяет лучше использовать соединение.
  • Последнее изменение
    • Последняя измененная дата для запрошенного объекта в формате RFC 2822
    • Пример: header('Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT');
    • См. Функцию filemtime и date для ее форматирования в требуемом формате RFC 2822
      • Пример: header('Last-Modified: '.date(DATE_RFC2822, filemtime($filename)));
    • Вы можете выйти из сценария после отправки 304, если время изменения файла одинаково.
  • код состояния
    • Пример: header("HTTP/1.1 304 Not Modified");
    • вы можете выйти и не отправлять изображение еще раз

Для последнего измененного времени найдите это в $_SERVER

  • If-Modified-Since
    • Позволяет возвращать 304 Not Modified, если содержимое не изменяется
    • Пример: If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
    • В $_SERVER с ключом http_if_modified_since

Список ответов HTTP-заголовков

Чтобы добиться чего-то подобного, ваш скрипт должен будет:

  • отправьте правильные заголовки, которые зависят от типа изображения: image / gif, image / png, image / jpeg, …
  • отправить данные изображения
  • убедившись, что ничего не отправлено (нет пробела, нет ничего)

Это делается с помощью функции header с некоторым кодом:

 header("Content-type: image/gif"); 

Или

 header("Content-type: image/jpeg"); 

или что-то еще, в зависимости от типа изображения.

Чтобы отправить данные изображения, вы можете использовать функцию readfile :

Читает файл и записывает его в выходной буфер.

Таким образом, в одной функции вы оба читаете файл и выводите его содержимое.

В качестве опоры:

  • вы должны установить определенную систему безопасности, чтобы пользователи не могли запрашивать что-то, что им нужно, через ваш скрипт: вы должны убедиться, что оно служит только для изображений, из ожидаемого вами каталога; например, serveImage.php?file=/etc/passwd должен быть в порядке.
  • Если вы просто хотите получить количество раз, когда файл загружался каждый день, анализ файла журнала Apache может быть хорошей идеей (через серийный запуск cron каждый день в 00:05, который анализирует журнал за день до , например) ; у вас не будет статистики в реальном времени, но для этого потребуется меньше ресурсов на вашем сервере (без использования PHP для статических файлов)

Я использую функцию «passthru» для вызова команды «cat», например:

 header('Content-type: image/jpeg'); passthru('cat /path/to/image/file.jpg'); 

Работает на Linux. Экономит ресурсы.

Вместо того, чтобы изменять URL-адрес прямого изображения в HTML, вы можете поместить строку в конфигурацию Apache или .htaccess чтобы переписать все запросы изображений в каталоге на php-скрипт. Затем в этом скрипте вы можете использовать заголовки запросов и массив $_server для обработки запроса и обслуживания файла.

Сначала в вашем .htaccess:

 RewriteRule ^(.*)\.jpg$ serve.php [NC] RewriteRule ^(.*)\.jpeg$ serve.php [NC] RewriteRule ^(.*)\.png$ serve.php [NC] RewriteRule ^(.*)\.gif$ serve.php [NC] RewriteRule ^(.*)\.bmp$ serve.php [NC] 

Скрипт serve.php должен находиться в том же каталоге, что и .htaccess . Вы, вероятно, напишете что-то вроде этого:

 <?php $filepath=$_SERVER['REQUEST_URI']; $filepath='.'.$filepath; if (file_exists($filepath)) { touch($filepath,filemtime($filepath),time()); // this will just record the time of access in file inode. you can write your own code to do whatever $path_parts=pathinfo($filepath); switch(strtolower($path_parts['extension'])) { case "gif": header("Content-type: image/gif"); break; case "jpg": case "jpeg": header("Content-type: image/jpeg"); break; case "png": header("Content-type: image/png"); break; case "bmp": header("Content-type: image/bmp"); break; } header("Accept-Ranges: bytes"); header('Content-Length: ' . filesize($filepath)); header("Last-Modified: Fri, 03 Mar 2004 06:32:31 GMT"); readfile($filepath); } else { header( "HTTP/1.0 404 Not Found"); header("Content-type: image/jpeg"); header('Content-Length: ' . filesize("404_files.jpg")); header("Accept-Ranges: bytes"); header("Last-Modified: Fri, 03 Mar 2004 06:32:31 GMT"); readfile("404_files.jpg"); } /* By Samer Mhana www.dorar-aliraq.net */ ?> 

(Этот скрипт можно улучшить!)

Вероятно, вам лучше изучить журналы доступа к серверу для этого. Запуск всех изображений через php может привести к загрузке вашего сервера.

Кроме того, если вы хотите, чтобы пользователь увидел реальное имя файла вместо вашего имени сценария, когда пользовательский RMC на изображении и выбирает «Сохранить как», вам также необходимо установить этот заголовок:

 header('Content-Disposition: filename=$filename'); 

Я также обслуживаю свои изображения с помощью файла readfile, но я прошел лишнюю милю как для обеспечения безопасности, так и для дополнительной функциональности.

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

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

Таким образом, для обслуживания упрощенного рабочего процесса было бы так (не может размещать здесь производственный код):

1) получить идентификатор запрашиваемого изображения

2) Посмотрите его в базе данных

3) Выбросить заголовки на основе расширения («jpg» переназначается на «jpeg» при загрузке)

4) readfile("/images/$id.$extension");

5) Необязательно, защищать / images / dir, чтобы он не мог быть проиндексирован (не проблема в моей собственной системе, так как он сопоставляет URLS, например / image / view / 11, с чем-то вроде /index.php?module=image&action=view&id=11 )