Symfony2: как отобразить/загрузить поле BLOB

Для моего клиента я должен использовать хранилище blob для некоторых различных файлов.

Итак, я создал независимый пакет с классом Blob, который расширяет Doctrine\DBAL\Types\Type. и с функцией загрузки в классе пакетов.

Это работает очень хорошо, я могу писать в базе данных данных Blob.

Но я не могу загрузить какой-либо документ после:/

У меня есть:

public function downloadAction($id) {
    $em = $this->getDoctrine()->getManager();

    /* @var $entity Document */
    $entity = $em->getRepository('Lille3SapBundle:Document')->find($id);

    if (!$entity) {
        throw $this->createNotFoundException('Unable to find Document entity.');
    }

    $file = $entity->getFichier();

    $response = new \Symfony\Component\HttpFoundation\Response($file, 200, array(
        'Content-Type' => 'application/octet-stream',
        'Content-Length' => sizeof($file),
        'Content-Disposition' => 'attachment; filename="'.$entity->getNomDocument().'"',
    ));

    return $response;
}

и у меня есть Исключение: Содержимое ответа должно быть строкой или объектом, реализующим __toString(), "ресурс".

на самом деле, значения $file не являются ожидаемым BLOB, но что-то вроде Resource id # 123

- > У меня есть значения полей данных blob-данных, и они в порядке в базе данных

Итак, как я могу заставить контроллер иметь строку blob, а не идентификатор ресурса # 111

Ответ 1

Вы все еще можете использовать поле BLOB для своего поля в БД по мере того, как вы изначально планировали.

В createAction хранят данные как обычно (без base64_encode()):

$stream = fopen($entity->getFichier(),'rb');
$entity->setFichier(stream_get_contents($stream));

и в downloadAction просто используйте:

$file = $entity->getFichier();
$response = new \Symfony\Component\HttpFoundation\Response(stream_get_contents($file), 200, array(
    'Content-Type' => 'application/octet-stream',
    'Content-Length' => sizeof($file),
    'Content-Disposition' => 'attachment; filename="'.$entity->getNomDocument().'"',
));

return $response;

Объяснение:

BLOB поля рассматриваются как переменная ресурса, которые не имеют реализации __toString().

gettype($file) -> "resource"
get_resource_type($file) -> "stream"

stream_get_contents ($ file) создает магию: получает содержимое STRING из переменной ресурса.

Ответ 2

Хорошо, у меня есть (очень uggly) решение:

Во-первых: я изменил тип данных blob на текст для атрибута файла объекта Document.

Во-вторых: в createAction я изменил вызов setFichier:

$stream = fopen($entity->getFichier(),'rb');
$entity->setFichier(base64_encode(stream_get_contents($stream)));

В-третьих: в файле downloadAction я декодирую текстовое поле text base64:

$file = $entity->getFichier();              
$response = new \Symfony\Component\HttpFoundation\Response(base64_decode($file), 200, array(
        'Content-Type' => 'application/octet-stream',
        'Content-Length' => sizeof($file),
        'Content-Disposition' => 'attachment; filename="'.$entity->getNomDocument().'"',
));

return $response;

И теперь я могу сохранять и загружать файлы как способ blob...