web-dev-qa-db-ja.com

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()、 "resource"を実装する文字列またはオブジェクトである必要があります。

実際、$ file値は期待されるBLOBではなく、Resource id#12のようなものです。

-> BLOBデータフィールドの値を確認しましたが、データベースで問題ありません

では、コントローラーに強制的にblob行を持たせ、Resource id#111ではないようにするにはどうすればよいですか?

16
saillantist

最初に計画したように、DBのフィールドに[〜#〜] 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 [〜#〜]フィールドはresource変数として扱われ、__ toString()が実装されていません。

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

stream_get_contents($ file)ここで魔法をかけます:[〜#〜] string [〜#〜]リソース変数からコンテンツを取得します。

27
Rafal Gradziel

さて、私は(非常に醜い)解決策を持っています:

まず、Documentエンティティのファイル属性のデータ型blobtextに変更しました。

次に、createActionで、setFichier呼び出しを変更しました。

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

3番目:downloadActionで、テキスト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;

そして今、私はブロブの方法としてファイルを永続化してダウンロードすることができます...

1
saillantist