Допустимые изображения, выводимые PHP, всегда «содержат ошибки», что может быть причиной этого? - PullRequest
5 голосов
/ 10 сентября 2011

Несколько месяцев назад я написал сайт для клиента, использующий PHP 5.3.Он отлично работает на моем собственном веб-сервере LAMP.Однако, когда он попытался установить его на своем собственном сервере (в настоящее время это сервер OVH, на котором запущен DirectAdmin в CentOS 5), он столкнулся с проблемой, с которой мне трудно разобраться.

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

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

header("Content-type: image/jpeg");
ob_start();
echo file_get_contents($path);
$size = ob_get_length();
$img = ob_get_contents();
ob_end_clean();
header ("Content-length: " . $size);
echo $img;

К сожалению, это всегда возвращает поврежденное изображение (в Firefox «Изображение не может быть отображено, поскольку оно содержит ошибки»).Теперь, после тщательного тестирования, я знаю, что:

  • Изображения правильно загружены на сервер.Данные изображения, хранящиеся на веб-сервере, действительны и могут быть получены через FTP как обычное изображение.

  • Если я сохраню $ img в файле непосредственно перед последней строкой предыдущего скрипта,например так:

    $fh = fopen("test.jpg", "w");
    fwrite($fh, $img);
    fclose($fh);
    

    Это также сохранит правильные данные изображения в файл.Таким образом, данные сохраняются непосредственно перед отправкой в ​​веб-браузер пользователя.

  • Заголовки отправляются корректно.

Однако!Если я использую текстовый / обычный заголовок, а не image / jpeg, я вижу, что возвращаемый тарабарщина отличается от отображаемого тарабарщины, если я открываю файл локально с помощью блокнота (или отправляю изображение напрямую через apache в виде текстового файла).На исходном изображении я вижу некоторые EXIF.На изображении, сгенерированном PHP и затем отправленном в веб-браузер пользователя, я все еще вижу магический код JFIF (для формата файлов JPEG с изображениями), но все остальное выглядит иначе.связанная проблема на PHP или Apache, связанная с кодированием, буферизацией, сжатием контента или чем-то в этом роде.Кто-нибудь знает что-нибудь, что я могу попытаться решить эту проблему?

РЕДАКТИРОВАТЬ:

Изменен сценарий для использования:

$img = file_get_contents($path);
$size = filesize($path);

Проблема остается неизменной, но содержание сейчасвыглядит точно так же, сравнивая реальное изображение с изображением, отправленным из PHP.Согласно заголовкам, кодировка контента - это gzip.Есть идеи?

Ответы [ 3 ]

3 голосов
/ 10 сентября 2011

Что ж, после некоторого расследования это оказалось печально известной подписью Byte Order Mark (в сочетании, конечно, с буферизацией вывода, которая подавляла ошибку) в скрипте PHP.
Кажется, просто повторное сохранение файла без спецификации решит проблему

это работает?

header("Content-type: image/jpeg");
echo file_get_contents($path);

или это?

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

скачайте это изображение (используя wget или сделайте ссылку на него и используйте «Сохранить как») и увидите разницу. Это может пролить свет на причину

И да. Обь тут абсолютно нечего делать. если вы хотите получить размер файла - для этого есть (сюрприз!) функция

header("Content-type: image/jpeg");
header ("Content-length: " . filesize($path));
readfile($path);
1 голос
/ 08 января 2017

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

"ха! Вот и все! Подпись UTF-8 и маска байтов это! Это в вашем PHP-скрипте. Сохраните его без этой подписи "

Я буквально часами пытался выяснить, почему изображения не отображаются в браузере - проблемане только относится к коду в вопросе, но также может появляться при использовании заголовков php с readfile и file_get_contents.

Благодаря Твоему здравому смыслу и Защищено дляподняв вопрос

Я решил это, изменив кодировку страницы, на которой размещен код - UTF-8 вроде бы в порядке, но BOM (Byte Order Mask) должна пойти.То, как вы делаете изменения, зависит от программного обеспечения, которое вы используете для редактирования - я использую старую версию Dreamweaver, в которой я могу отменить использование спецификации в «свойствах страницы».

1 голос
/ 10 сентября 2011

Во-первых, если вы еще этого не сделали, я бы подтвердил, что проблемное изображение действительно является изображением в формате JPEG, а не каким-либо другим типом изображения.Многие программы просмотра изображений будут отображать их правильно, даже если задан неправильный тип или расширение, но это может вызвать проблемы, если вы отправляете тип jpeg для не-jpeg.

Во-вторых, я бы переместил ob_start ()первая строка вашего файла.

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

Наконец, если у вас установлен GD и он соответствует вашим требованиям использования, это альтернативное решение может работать для вас.

ob_start();
$image = imagecreatefromjpeg( $path );
if (!$image ) {
    // error trapping / other logic here
}
ob_end_clean();
header( "Content-type: image/jpeg" );
@imagejpeg( $image );
if ( $image ) {
    imagedestroy( $image );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...