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

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

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

www.site.com/image1.jpg

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

  • Content-Length
    • Длина тела ответа в октетах (8-разрядные байты)
    • Пример: header('Content-Length: 348');
    • См. функцию filesize
    • Позволяет лучше использовать соединение.
  • Last-Modified
    • Последняя измененная дата для запрошенного объекта в формате 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)));
    • Вы можете выйти из script после отправки 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-заголовков

Ответ 3

Чтобы достичь чего-то подобного, вашему script необходимо будет:

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

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

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

или

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

или что угодно, в зависимости от типа изображения.


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

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

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


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

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

Ответ 4

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

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

Работает на Linux. Сохраняет ресурсы.

Ответ 5

Вместо того, чтобы изменять URL-адрес прямого изображения в HTML, вы можете поместить строку в конфигурацию Apache или .htaccess, чтобы переписать все запросы изображений в каталоге на PHP скрипт. Затем в script вы можете использовать заголовки запроса и массив $_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]

script 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
*/
?>

(Этот script можно улучшить!)

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

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

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

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

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

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

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

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

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