После многих часов,
Я прибил мою проблему относительно загрузки изображения с помощью запроса https. Когда я получаю доступ к изображению с жестким путем (https://mysite/tmp/file.jpg)
, apache возвращает его с успехом, и я могу просматривать его в браузере без каких-либо дополнительных манипуляций. Когда я пытаюсь получить к нему доступ с другим путем (https://mysite/files/file.jpg)
, чтобы контролировать его доступ с помощью php, я получаю ответ от моего php-кода, но я не могу просмотреть изображение в браузере ,
Описание среды:
mysite/tmp/file.jpg mysite/files/.htaccess //... no files; handled by Silex router. here is the .htaccess: --- <IfModule mod_rewrite.c> RewriteEngine On RewriteRule ^ ../web/index.php [L] </IfModule> ---
Вот три метода:
Метод 1: Silex sendFile () прямой метод>
$app->get('/files/{onefile}', function ($onefile) use ($app) { // Validate authorization; if ok, then return $app->sendFile('/var/www/mysite/tmp/' . $onefile); });
Способ 2: потоковая передача Silex>
$app->get('/files/{onefile}', function ($onefile) use ($app) { // Validate authorization; if ok, then $stream = function () use ($file) { readfile($file); }; return $app->stream($stream, 200, array('Content-Type' => 'image/jpeg'));
Способ 3: стиль Symfony2>
$app->get('/files/{onefile}', function ($onefile) use ($app) { // Validate authorization; if ok, then $exactFile="/var/www/mysite/tmp/" . $onefile; $response = new StreamedResponse(); $response->setCallback(function () use ($exactFile) { $fp = fopen($exactFile, 'rb'); fpassthru($fp); }); $response->headers->set('Content-Type', 'image/jpg'); $response->headers->set('Content-length', filesize($exactFile)); $response->headers->set('Connection', 'Keep-Alive'); $response->headers->set('Accept-Ranges','bytes'); $response->send();
Это то, что Chrome представляет:
С этим изображением Chrome это запрос Http (Https или нет, тот же результат)
Request URL:https://mysite/files/tmpphp0XkXn9.jpg Request Method:GET Status Code:200 OK Request Headers: Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding:gzip,deflate,sdch Accept-Language:en-US,en;q=0.8 Cache-Control:no-cache Connection:keep-alive Cookie:XDEBUG_SESSION=netbeans-xdebug; _MYCOOKIE=u1k1vafhaqik2d4jknko3c94j1 Host:mysite Pragma:no-cache User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.110 Safari/537.36 Response Headers: Accept-Ranges:bytes Cache-Control:no-cache Connection:Keep-Alive, Keep-Alive Content-Length:39497 Content-Type:image/jpg Date:Thu, 13 Jun 2013 13:44:55 GMT Keep-Alive:timeout=15, max=99 Server:Apache/2.2.16 (Debian) X-Powered-By:PHP/5.3.3-7+squeeze15
Другие тесты, проведенные для устранения возможного нежелательного поведения:
set-buffer-file-coding-system utf-8
). Кроме того, чтобы избежать неизвестных файлов с помеченными тегами, я выполнил следующую команду в каталоге mysite ( grep -rl $'\xEF\xBB\xBF' .
). Ничего необычного не появилось. ОБНОВИТЬ:
Если посмотреть на файлы (изображения), полученные браузером ( save as
на каждом изображении), это то, что помогает мне инструмент (Hex Friend), но я до сих пор не понимаю, почему:
Сравнение двух файлов
В начале двоичного файла я получаю эту разницу:
В конце двоичного файла я получаю эту разницу:
Вопрос: Как я могу вернуть изображение (по потоку или какой-либо другой технике) с помощью php-кода и просмотреть его в браузере? Все методы PHP-кода возвращают один и тот же результат, я подозреваю, что проблема с окружением. Есть ли настройка среды, которая может вызвать ошибку, которую я экспериментирую?
Я не доволен этим решением (A PATCH ), но проблема исправлена, добавив следующий вызов:
$app->get('/files/{onefile}', function ($onefile) use ($app) { ob_end_clean(); // ob_clean() gave me the same result. ... }
Хорошо, это исправлено, но может ли кто-нибудь объяснить мне, как исправить это более разумно?
ОБНОВИТЬ
Что случилось ?:
Это то, что моя интерпретация:
Дополнительные строки новой строки остаются в исходных файлах orignal php для непреднамеренной позиции! Оказывается, когда у вас есть php-файл
<?php ... ?>
где вы оставили некоторые новые строки (или пробелы) после ?>
, эти новые строки будут добавлены в выходной буфер. Затем, пытаясь передать поток на выходной файл, они будут складывать новые строки и помещать их туда, где они принадлежат: в потоке заголовка или в потоке нижнего колонтитула. Наличие фиксированного размера для потока (равного размеру изображения) будет принимать специально дополнительные символы заголовка и соответственно сдвигать байты, выводимые в браузер. Я подозревал, что я добавляю ровно 5 символов ( 0A 0A 20 0A 0A
), соответствующих ( linefeed linefeed space linefeed linefeed
), обнаруженной в полученном изображении из браузера. Теперь браузер не распознает структуру изображения, будучи сдвигом со смещения 0, из 5 не логических символов для двоичного изображения. Поэтому браузер может показывать только сломанное изображение.
Также посмотрите: Еще одна помощь SO fix
Посоветуйте разработчику фреймворка PHP:
Если вы предоставляете эквивалентный метод sendFile()
, возможно, вы должны выбросить Exception
, когда ob_get_contents()
не возвращает пустой буфер, перед потоковой передачей на вывод!
На данный момент:
Этот небольшой пакетный файл Linux может по крайней мере позволить вам найти, где ваш код должен быть очищен. После использования я смог удалить ob_end_clean()
… после анализа вывода этого маленького скрипта. Он сообщает вам подозрительные php-файлы, которые могут содержать дополнительное пространство или новую строку в конце ваших php-файлов. Просто выполните и вручную исправьте файлы:
#!/bin/bash for phpfiles in $(ls -1R *.php); do hexdump -e '1/1 "%.2x"' $phpfiles | tail -1 >endofphpfile; if [ `cat endofphpfile` = "3f3e" ]; then echo "OK.................File $phpfiles" else thisout=`cat endofphpfile` echo "File $phpfiles: Suspucious. Check ($thisout) at the EOF; it should end with '?>' (in hex 3f3e) " fi done
Это, безусловно, может быть улучшено, но это должно, по крайней мере, помочь кому угодно!
не используйте закрытие ?> … это против стандартов кодирования Symfony.
Против PSR-2 будет более конкретным.
Все файлы PHP ДОЛЖНЫ заканчиваться пустой пустой строкой.
Закрывающий?> Тег ДОЛЖЕН быть опущен из файлов, содержащих только PHP.
Причина этого частично в том, что вы испытали.
Такое поведение иногда вызывает и спецификация .
проверьте, что ни один из ваших файлов не содержит байтовую марку!