Laravel: Créer et télécharger un fichier temporaire

Quand on développe des applications web, il arrive régulièrement d’avoir besoin de générer un fichier uniquement pour le faire télécharger par l’utilisateur. Il n’est donc pas nécessaire de le stocker sur le serveur. Heureusement, en PHP on a la possibilité de créer des fichiers temporaires sans avoir à les stocker sur le serveur et à les supprimer ensuite.

Je vais vous allez apprendre à générer un fichier CSV temporaire. Puis à l’envoyer en pièce jointe d’un e-mail ou le télécharger par l’utilisateur.

Génération du fichier temporaire

PHP nous met à disposition un nombre importants de flux I/O. Vous trouverez leur liste ici dans la documentation: https://www.php.net/manual/fr/wrappers.php.php

Nous allons nous concentrer sur le flux php://temp qui permet d’ouvrir un fichier temporaire. Le fichier est supprimé lorsque le descripteur de fichier est fermé. L’option /maxmemory: permet de définir la taille maximale à stocker en mémoire avant que le fichier soit créé dans un répertoire temporaire. Notez que cela ne change rien à l’utilisation, c’est juste une option pour optimiser la gestion mémoire.

$fd = fopen('php://temp/maxmemory:1048576', 'w');
if ($fd === false) {
     die('Failed to open temporary file');
}

Nous allons en suite utiliser ce descripteur de fichier $fd comme un fichier classique pour écrire du contenu en CSV. J’ai commenté le processus dans le code suivant:

$headers = ['header1', 'header2', 'header3'];
$data = [
        ['data1', 'data2', 'data3'],
        ['data1', 'data2', 'data3'],
        ['data1', 'data2', 'data3'],
    ];
    
// Ecriture de la première ligne
fputcsv($fd, $header);

// Ecriture de chaque ligne de données
foreach ($data as $record) {
    fputcsv($fd, array_values($record));
}

// Retour au début du fichier temporaire
rewind($fd);

// Lecture du contenu du fichier dans une variable
$csv = stream_get_contents($fd);

// Fermeture du fichier temporaire et libération de la mémoire
fclose($fd);

Nous avons maintenant le contenu du fichier CSV dans la variable $csv

Téléchargement du fichier temporaire

Il existe beaucoup de moyens différents en PHP et Laravel pour faire télécharger le contenu d’une variable au client. Une approche que je trouve particulièrement élégante est l’utilisation d’une macro de réponse. (Voir documentation Laravel: https://laravel.com/docs/9.x/responses#response-macros)

Une macro permet d’appliquer un traitement particulier à une réponse, elle peut prendre des paramètres. C’est un peu le même principe que les middlewares qui viennent ajouter des comportements lors de la gestion des requêtes. Ici on va utiliser une macro pour générer les headers nécessaire au téléchargement d’un fichier CSV.

Pour cela, allez dans App\Providers\AppServiceProvider puis ajoutez le code suivant dans la méthode boot :

public function boot()
{
    \Response::macro('attachment', function ($content, $filename) {
    
        $headers = [
            'Content-type'        => 'text/csv',
            'Content-Disposition' => 'attachment; filename="'.$filename.'"',
        ];
    
        return \Response::make($content, 200, $headers);
    
    });
}

Il suffit ensuite d’appeler notre macro depuis un controller par exemple pour télécharger le fichier:

return response()->attachment($csv);

Envoyer le CSV en pièce jointe d’un email

La création d’un email en Laravel est un sujet à part entière, pour en savoir plus, la documentation explique tout par ici: https://laravel.com/docs/9.x/mail

Une fois que votre message créé, utilisez la méthode attachData qui permet d’ajouter une pièce jointe à partir d’une variable. Nous allons donc reprendre notre variable $csv initialisée plus haut par notre fichier temporaire:

$message->attachData($csv, 'filename.csv');

1 réflexion sur “Laravel: Créer et télécharger un fichier temporaire”

  1. Ping : PHP Convertir l'encodage d'un fichier en UTF-8 (fopen) - YannPl

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *