Downloading of a dynamically generated file from a Symfony controller

Published on 2021-01-10 • Modified on 2021-01-10

In a previous snippet, we saw how to force the dowload of a file that already exists on the file system. But, generally, you want to provide dynamic content like for a CSV export. In this one, we will see how to do with using a temporary system file, so we don't have to generate a file stored in the public directory; that would be a security issue.



// src/Controller/Snippet/Snippet129Trait.php

namespace App\Controller\Snippet;

use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpKernel\KernelInterface;

 * I am using a PHP trait to isolate each snippet in a file.
 * This code should be called from a Symfony controller extending AbstractController (as of Symfony 4.2)
 * or Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
 * Services are injected in the main controller constructor..
 * @property KernelInterface $kernel
trait Snippet129Trait
    public function snippet129(): BinaryFileResponse
        $tmpFileName = (new Filesystem())->tempnam(sys_get_temp_dir(), 'sb_');
        $tmpFile = fopen($tmpFileName, 'wb+');
        if (!is_resource($tmpFile)) {
            throw new \RuntimeException('Unable to create a temporary file.');

        $data = [
            ['name', 'firstname', 'age'],
            ['COil', 'Doo', random_int(30, 42)],
            ['Fab', 'Pot', random_int(30, 42)],
            ['Glas', 'Dun', random_int(30, 42)],
        foreach ($data as $line) {
            fputcsv($tmpFile, $line, ';');
        $response = $this->file(stream_get_meta_data($tmpFile)['uri'], 'dynamic-csv-file.csv');
        $response->headers->set('Content-type', 'application/csv');

        return $response; // That's it! 😁

 Run this snippet  More on Stackoverflow  Random snippet