How to force file download from controller using BinaryFileResponse

Letting users download a file is a common task.

Sometimes a simple direct link is sufficient, but if you want to implement something a little more sophisticated you could serve the file without directly exposing it, or with another filename, or execute some logic before serving the file, or again log the action in a database and then serve the file.

Symfony >= 2.2 provides the BinayFileResponse() class for this purpose; this guide is a simple but working implementation.

This method consists in creating a single action in a Symfony Controller.

Return a BinaryFileResponse object

A new action will be created. It will receive the parameter filename and return a BinaryFileResponse response.

Uses the component FileSystem to check the existence of a file (thanks @flo_schield).

Here is the code:


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

class FooController extends Controller
     * Serve a file by forcing the download
     * @Route("/download/{filename}", name="download_file", requirements={"filename": ".+"})
    public function downloadFileAction($filename)
         * $basePath can be either exposed (typically inside web/)
         * or "internal"
        $basePath = $this->container->getParameter('kernel.root_dir').'/Resources/my_custom_folder';

        $filePath = $basePath.'/'.$filename;

        // check if file exists
        $fs = new FileSystem();
        if (!$fs->exists($filePath)) {
            throw $this->createNotFoundException();

        // prepare BinaryFileResponse
        $response = new BinaryFileResponse($filePath);
            iconv('UTF-8', 'ASCII//TRANSLIT', $filename)

        return $response;

Note: to use BinaryFileResponse you will need Symfony >= 2.2.0


  1. Be sure not to have RewriteCond %{REQUEST_FILENAME} !-f in .htaccess (thanks Eric Grivilers)

  2. Outside of Symfony, you need to call prepare(Request $request) to make the BinaryFileResponse work (thanks Julius Beckmann @h4cc):

    $response = new Symfony\Component\HttpFoundation\BinaryFileResponse($filePath);


The download_file route accepts as parameter the filename of the file you will serve to the user. Obviously you are free to implement a smarter way to compose the url, as well as to serve a better filename.

Alternative solution

If for some reason this is not working, here is the raw PHP code to serve a file:

        // check if file exists

        header('Content-Description: File Transfer');
        header('Content-Type: application/pdf');
        header('Content-Disposition: inline; filename=' . basename($filename));
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($filePath));


A useful resource about BinaryFileResponse (and nginx) is