224 votes

Créer un fichier CSV pour un utilisateur en PHP

J'ai des données dans une base de données MySQL. J'envoie à l'utilisateur une URL pour récupérer ses données dans un fichier CSV.

Je m'occupe de l'envoi du lien par e-mail, de la requête MySQL, etc.

Comment puis-je, lorsqu'ils cliquent sur le lien, avoir une pop-up pour télécharger un CVS avec l'enregistrement de MySQL ?

J'ai déjà toutes les informations nécessaires pour obtenir l'enregistrement. Je ne vois pas comment faire en sorte que PHP crée le fichier CSV et laisse les utilisateurs télécharger un fichier avec une extension .csv.

477voto

andreyne Points 3652
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=file.csv");
header("Pragma: no-cache");
header("Expires: 0");

outputCSV(array(
    array("name 1", "age 1", "city 1"),
    array("name 2", "age 2", "city 2"),
    array("name 3", "age 3", "city 3")
));

function outputCSV($data) {
    $output = fopen("php://output", "w");
    foreach ($data as $row) {
        fputcsv($output, $row); // here you can change delimiter/enclosure
    }
    fclose($output);
}

66 votes

Plus de gens doivent voir ça et voter pour. C'est facilement la meilleure réponse de cette page. PHP a déjà des fonctions intégrées pour formater le contenu des CSV. Tout le monde devrait les utiliser. Excellente réponse, @Andrey :)

2 votes

Dommage que fputcsv() ne fonctionne pas correctement :( bugs.php.net/bug.php?id=50686

5 votes

Sympa, mais le outputCSV est inutilement compliquée. Vous pouvez simplement foreach sur $array en envoyant ses valeurs directement dans fputcsv . Pas besoin de ça __outputCSV et le array_walk :) foreach($data as $vals) {fputcsv($filehandler,$vals);}

292voto

Oleg Barshay Points 2126

Essayez :

header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=file.csv");
header("Pragma: no-cache");
header("Expires: 0");

echo "record1,record2,record3\n";

etc.

Edit : Voici un bout de code que j'utilise pour coder optionnellement les champs CSV :

function maybeEncodeCSVField($string) {
    if(strpos($string, ',') !== false || strpos($string, '"') !== false || strpos($string, "\n") !== false) {
        $string = '"' . str_replace('"', '""', $string) . '"';
    }
    return $string;
}

11 votes

Notez que les règles pour les CSV sont importantes. Pour assurer un bon affichage, mettez des doubles guillemets autour de vos champs, et n'oubliez pas de remplacer les doubles guillemets à l'intérieur des champs par des doubles guillemets : `echo '"".str_replace('"','""',$record1).'",""'.str_replace....

46 votes

Juste pour clarifier, l'en-tête HTTP Content-Type correct pour CSV est text/csv, et non application/csv. Je doute qu'un navigateur moderne s'en préoccupe, mais puisqu'il existe des normes, autant les utiliser.

10 votes

En général, veuillez suivre la RFC 4180 lors de la génération de fichiers CSV. outils.ietf.org/html/rfc4180

19voto

Xeoncross Points 13263

Voici une version améliorée de la fonction de php.net que @Andrew a postée.

function download_csv_results($results, $name = NULL)
{
    if( ! $name)
    {
        $name = md5(uniqid() . microtime(TRUE) . mt_rand()). '.csv';
    }

    header('Content-Type: text/csv');
    header('Content-Disposition: attachment; filename='. $name);
    header('Pragma: no-cache');
    header("Expires: 0");

    $outstream = fopen("php://output", "w");

    foreach($results as $result)
    {
        fputcsv($outstream, $result);
    }

    fclose($outstream);
}

Il est vraiment facile à utiliser et fonctionne parfaitement avec les ensembles de résultats MySQL(i)/PDO.

download_csv_results($results, 'your_name_here.csv');

N'oubliez pas de exit() après avoir appelé cette fonction si vous avez terminé la page.

0 votes

Comment changer le séparateur de , en ; ?

1 votes

Comment ajouter un bouton, pour déclencher cet événement, afin que l'utilisateur puisse télécharger le fichier CSV à la demande ?

0 votes

J'ai l'erreur "SyntaxError : Unexpected token ILLEGAL" avec la ligne "fopen("php://output", "w") ;" Lorsque je la change en "$fp = fopen('stats.csv', 'w') ;", l'erreur n'apparaît pas. Mais bien sûr, cela ne fonctionne pas. Comment puis-je résoudre ce problème ?

16voto

Stan Points 453

En plus de tout ce qui a déjà été dit, vous pourriez avoir besoin d'ajouter :

header("Content-Transfer-Encoding: UTF-8");

C'est très utile pour gérer plusieurs langues, comme les noms de personnes ou les villes.

9voto

typemismatch Points 1217

Créez votre fichier puis renvoyez une référence à celui-ci avec l'en-tête correct pour déclencher l'enregistrement sous - modifiez les éléments suivants si nécessaire. Placez vos données CSV dans $csvdata.

$fname = 'myCSV.csv';
$fp = fopen($fname,'w');
fwrite($fp,$csvdata);
fclose($fp);

header('Content-type: application/csv');
header("Content-Disposition: inline; filename=".$fname);
readfile($fname);

1 votes

Utilisation de "inline" (en ligne) Content-Disposition signifie que le navigateur doit essayer de l'afficher sans le télécharger (IE a tendance à intégrer une instance Excel pour cela). "attachment" est ce qui est nécessaire pour forcer un téléchargement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X