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.
<?php
declare(strict_types=1);
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($tmpFileName, 'dynamic-csv-file.csv');
$response->headers->set('Content-type', 'application/csv');
fclose($tmpFile);
return $response; // That's it! 😁
}
}
Run this snippet More on Stackoverflow Random snippet