web-dev-qa-db-ja.com

Symfony2-強制ファイルのダウンロード

ユーザーがダウンロードリンクをクリックしたときにファイルをダウンロードしようとしています。

コントローラー内:

    $response = new Response();
    $response->headers->set('Content-type', 'application/octect-stream');
    $response->headers->set('Content-Disposition', sprintf('attachment; filename="%s"', $filename));
    $response->headers->set('Content-Length', filesize($filename));

    return $response;

これにより、ファイルを保存するためのダイアログボックスが開きますが、ファイルが0バイトであると表示されます。そしてそれを次のように変更します:

        $response = new Response();
        $response->headers->set('Content-type', 'application/octect-stream');
        $response->headers->set('Content-Disposition', sprintf('attachment; filename="%s"', $filename));
        $response->headers->set('Content-Length', filesize($filename));
        $response->headers->set('Content-Transfer-Encoding', 'binary');
        $response->setContent(readfile($filename));

        return $response;

ファイルのダウンロードダイアログボックスの代わりに奇妙な文字の束を取得します。

最後に、「setContent」行を次のように切り替えます。

    $response->setContent(file_get_contents($filename));

PHPエラー:

致命的なエラー:許可されたメモリサイズ...

これを達成する方法についての手がかりはありますか?私は以前にPHP(wihtout MVC)でそれをやったことがありますが、Symfony2を通してそれを行うために何が欠けているのかわかりません...

多分解決策はPHP.INIでmemory_limitを設定することですが、それはベストプラクティスではないと思います...

52
Xavi

まず第一に、あなたの返信に感謝します。私はついにX-SendFileなしでこれを解決しました(これはおそらくベストプラクティスです)。とにかく、X-Sendfile Apacheモジュールが機能しない(共有ホスティング)ことができない人のために、ここに解決策があります:

// Generate response
$response = new Response();

// Set headers
$response->headers->set('Cache-Control', 'private');
$response->headers->set('Content-type', mime_content_type($filename));
$response->headers->set('Content-Disposition', 'attachment; filename="' . basename($filename) . '";');
$response->headers->set('Content-length', filesize($filename));

// Send headers before outputting anything
$response->sendHeaders();

$response->setContent(file_get_contents($filename));

return $response;

お役に立てれば!

49
Xavi

最も快適な解決策は

use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

$response = new BinaryFileResponse($file);
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT);

return $response;
84
denkweite

ApacheまたはNginxサーバーのタスクであるため、ファイルのダウンロードにPHPを使用しないでください。最良のオプションは、X-Accel-Redirect(Nginxの場合)/ X-Sendfile( Apacheの場合)ファイルのダウンロード用のヘッダー。

次のアクションスニペ​​ットを構成済みのNginxで使用して、Symfony2からファイルをダウンロードできます。

return new Response('', 200, array('X-Accel-Redirect' => $filename));

PD1: mod_xsendfileが設定されたApacheのコード:

return new Response('', 200, array(
    'X-Sendfile'          => $filename,
    'Content-type'        => 'application/octet-stream',
    'Content-Disposition' => sprintf('attachment; filename="%s"', $filename))
);
14
lisachenko

それが役立つかどうかわからないが、application/octet-stream not application/octect-stream

8
Pascal

Symfony 3.2では、 file()コントローラーヘルパー を使用できます。これは、前の回答で述べたBinaryFileResponseを作成するためのショートカットです:

public function fileAction()
{
    // send the file contents and force the browser to download it
    return $this->file('/path/to/some_file.pdf');
}
7
COil

アレキサンダーの応答に+1。

ただし、X-Sendfileを使用できない場合は、2.2で追加されたBinaryFileResponseを使用する必要があります。 http://symfony.com/doc/current/components/http_foundation/introduction.html#serving-files =

私のプロジェクトでは、結果は

$response = new \Symfony\Component\HttpFoundation\BinaryFileResponse($dir .DIRECTORY_SEPARATOR. $zipName);

$d = $response->headers->makeDisposition(
    ResponseHeaderBag::DISPOSITION_ATTACHMENT,
    $zipName
   );

$response->headers->set('Content-Disposition', $d);

return $response;
6
Jaycreation

ヘッダーを設定するオプションがない場合:

download属性は、サポートする必要があるブラウザーに応じて役立ちます。

<a href="{file url}" download>

または

<a href="{file url}" download="{a different file name}">

これは、すべてのレガシーブラウザでサポートされているわけではありません。ブラウザのサポートについては、このページを参照してください。

https://www.w3schools.com/tags/att_a_download.asp

2
Henry