Вернуть изображение как http-ответ от Listener Symfony2

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

Я хочу вместо отображения сообщения об ошибке "404 Not Found" вернуть правильное изображение. Для этого я создал таблицу базы данных, в которой хранятся старые ссылки и новые ссылки изображений, которые были удалены, перемещены или изменены.

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

Мой код:

class ExceptionListener
{
private $service_container;
private $router;

function __construct(Container $service_container, $router){
    $this->service_container = $service_container;
    $this->router = $router;
}

public function onKernelException(GetResponseForExceptionEvent $event){
    $exception = $event->getException();
    $request = $this->service_container->get('request');

    ...

    $document_root = $request->server->get('DOCUMENT_ROOT');
    $filename = realpath($document_root . '/'. '/path/to/new_image.jpg');
    $response = new \Symfony\Component\HttpFoundation\Response();
    $response->headers->set('Content-type',  'image/jpeg');
    $response->headers->set('Content-Disposition', 'inline; filename="' . basename($filename) . '";');
    $response->headers->set('Content-length', filesize($filename));
    $response->sendHeaders();
    $response->setContent(file_get_contents($filename));
    return $response;

    ...
}
}

Возникает следующая ошибка:

скриншот браузера

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

в контроллере работает нормально

Что я могу сделать, чтобы вернуть изображение от слушателя? спасибо


person Edgar Alfonso    schedule 22.01.2016    source источник
comment
Вам нужно установить ответ события, а не просто вернуть событие. Вы можете сделать это как $event->setResponse($response).   -  person qooplmao    schedule 23.01.2016


Ответы (1)


В фрагменте кода из вашего вопроса есть несколько неправильных вещей.

Во-первых, вы никогда не должны использовать службу запросов. Он устарел, начиная с Symfony 2.4, и был удален в Symfony 3.0. Вместо этого используйте стек запросов (request_stack).

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

Наконец, вам вообще не нужен сервисный контейнер для доступа к запросу, так как он доступен на событие.

Более того, вместо стандартного класса Response вы можете использовать класс BinaryFileResponse. Его цель — обслуживать файлы (посмотрите документы).

Вы можете значительно упростить свой слушатель:

use Symfony\Component\HttpFoundation\BinaryFileResponse;

class ExceptionListener
{
    private $router;

    function __construct($router)
    {
        $this->router = $router;
    }

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();
        // request is avialable on the event
        $request = $event->getRequest();

        // ...


        $file = 'path/to/file.txt';
        $response = new BinaryFileResponse($file);
        // ... set response parameters ...

        // finally, set the response on your event
        $event->setResponse($response);
    }
}
person Jakub Zalas    schedule 22.01.2016
comment
Спасибо, @JakubZalas, отлично работает с \Symfony\Component\HttpFoundation\Response();, но с BinaryFileResponse браузер показывает пустую страницу. Журналов ошибок нет. Это общая проблема? - person Edgar Alfonso; 23.01.2016