Téléchargement d'un fichier généré dynamiquement depuis un contrôleur Symfony

Publié le 10/01/2021 • Mis à jour le 10/01/2021


English language detected! 🇬🇧

  We noticed that your browser is using English. Do you want to read this post in this language?

Read the english version 🇬🇧 Close

Dans un snippet précédent, nous avons vu comment forcer le téléchargement d'un fichier existant à partir d'un contrôleur Symfony. Généralement on veut fournir du contenu dynamique comme lors d'un export CSV. Dans celui-ci ; nous allons utiliser un fichier temporaire pour ne pas avoir en générer un dans le répertoire public ; ce serait une faille de sécurité.


<?php

declare(strict_types=1);

// src/Controller/Snippet/Snippet129Trait.php

namespace App\Controller\Snippet;

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

/**
 * J'utilise un trait PHP afin d'isoler chaque snippet dans un fichier.
 * Ce code doit être apellé d'un contrôleur Symfony étendant AbstractController (depuis Symfony 4.2)
 * ou Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
 * Les services sont injectés dans le constructeur du contrôleur principal.
 *
 * @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! 😁
    }
}

 Exécuter le snippet  Plus sur Stackoverflow  Snippet aléatoire