Create a CSV File for a user in PHP
I have data in a MySQL database. I am sending the user a URL to get their data out as a CSV file. I have the e-mailing of the link, MySQL query, etc. covered. How can I, when they click the link, have a pop-up to download a CVS with the record from MySQL? I have all the information to get the record already. I just don’t see how to have PHP create the CSV file and let them download a file with a .csv extension.
20 Answers 20
header("Content-Type: text/csv"); header("Content-Disposition: attachment; filename=file.csv"); function outputCSV($data) < $output = fopen("php://output", "wb"); foreach ($data as $row) fputcsv($output, $row); // here you can change delimiter/enclosure fclose($output); >outputCSV(array( array("name 1", "age 1", "city 1"), array("name 2", "age 2", "city 2"), array("name 3", "age 3", "city 3") ));
More people need to see this and vote it up. This is easily the best answer on this page. PHP already has built-in functions for formatting CSV content. Everyone should use them. Great answer, @Andrey 🙂
Nice, but the outputCSV function is needlessly complicated. You can just foreach over $array , sending its values straight into fputcsv . No need for that __outputCSV and the array_walk 🙂 foreach($data as $vals)
I’m having some issues with French characters in the array because I eventually need the .csv to be open in Excel. It chokes on the accented characters. Things like «Prévalence»,»age 1″,»city 1″ Any ideas? Messing with UTF-8 hasn’t helped thus far.
Don’t know why but its not working in my case. I’m fetching rows from database as while($row as mysql_fetch_array($res)) <$data[] = $row;>. Also, I’m not getting what is php://output used for
header("Content-type: text/csv"); header("Content-Disposition: attachment; filename=file.csv"); header("Pragma: no-cache"); header("Expires: 0"); echo "record1,record2,record3\n"; die;
Edit: Here’s a snippet of code I use to optionally encode CSV fields:
function maybeEncodeCSVField($string) < if(strpos($string, ',') !== false || strpos($string, '"') !== false || strpos($string, "\n") !== false) < $string = '"' . str_replace('"', '""', $string) . '"'; >return $string; >
note the rules for CSVs are important. To ensure good display, put doublequotes around your fields, and don’t forget to replace double-quotes inside fields to double double-quotes: `echo ‘»‘.str_replace(‘»‘,'»»‘,$record1).'»,»‘.str_replace.
Just to clarify, the correct HTTP Content-Type header for CSV is text/csv, not application/csv. I doubt any modern browser will care either way, but since there are standards we might as well use them.
@Oleg Barshay: OMG, that RFC is a master piece: «If double-quotes are used to enclose fields, then a double-quote appearing inside a field must be escaped by preceding it with another double quote.». ANOTHER DOUBLE-QUOTE!
Here is an improved version of the function from php.net that @Andrew posted.
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", "wb"); foreach($results as $result) < fputcsv($outstream, $result); >fclose($outstream); >
It is really easy to use and works great with MySQL(i)/PDO result sets.
download_csv_results($results, 'your_name_here.csv');
Remember to exit() after calling this if you are done with the page.
how should we add a button, to trigger this event, so that user will be able to download the CSV file on demand ?
I’ll have «SyntaxError: Unexpected token ILLEGAL» error with the line «fopen(«php://output», «w»);» When I change it to «$fp = fopen(‘stats.csv’, ‘w’);» it doesn’t show error. But then of course it doesn’t work. How should I solve it ?
Add fputcsv($outstream, array_keys($results[0])); just before your foreach to also include column headers.
In addition to all already said, you might need to add:
header("Content-Transfer-Encoding: UTF-8");
It’s very useful when handling files with multiple languages in them, like people’s names, or cities.
Create your file then return a reference to it with the correct header to trigger the Save As — edit the following as needed. Put your CSV data into $csvdata.
$fname = 'myCSV.csv'; $fp = fopen($fname,'wb'); fwrite($fp,$csvdata); fclose($fp); header('Content-type: application/csv'); header("Content-Disposition: inline; filename mt24">)" data-controller="se-share-sheet" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f4.0%2f" data-se-share-sheet-license-name="CC BY-SA 4.0" data-s-popover-placement="bottom-start">Share)" title="">Improve this answer)">edited Sep 5, 2018 at 13:56 ntzm4,6632 gold badges30 silver badges35 bronze badgesanswered Oct 20, 2008 at 3:16 typemismatchtypemismatch2,0373 gold badges23 silver badges26 bronze badges