0

I'm having a bit of trouble exporting a csv file that is created from one of my mysql tables using php.

The code I'm using prints the correct data, but I can't see how to download this data in a csv file, providing a download link to the created file. I thought the browser was supposed to automatically provide the file for download, but it doesn't. (Could it be because the below code is called using ajax?)

Any help greatly appreciated - code below, S.

include('../cofig/config.php');    //db connection settings
$query = "SELECT * FROM isregistered";
$export = mysql_query($query) or die("Sql error : " . mysql_error());
$fields = mysql_num_fields($export);
for ($i = 0; $i < $fields; $i++) {
    $header .= mysql_field_name($export, $i) . "\t";
}
while ($row = mysql_fetch_row($export)) {
    $line = '';
    foreach ($row as $value) {
        if ((!isset($value) ) || ( $value == "" )) {
            $value = "\t";
        } else {
            $value = str_replace('"', '""', $value);
            $value = '"' . $value . '"' . "\t";
        }
        $line .= $value;
    }
    $data .= trim($line) . "\n";
}
$data = str_replace("\r", "", $data);

if ($data == "") {
    $data = "\n(0) Records Found!\n";
}
//header("Content-type: application/octet-stream"); //have tried all of these at sometime
//header("Content-type: text/x-csv");
header("Content-type: text/csv");
//header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=export.csv");
//header("Content-Disposition: attachment; filename=export.xls");
header("Pragma: no-cache");
header("Expires: 0");

echo '<a href="">Download Exported Data</a>'; //want my link to go in here...

print "$header\n$data";
Arend
  • 3,741
  • 2
  • 27
  • 37
ss888
  • 1,728
  • 5
  • 26
  • 48

5 Answers5

1

In essence, you can't output the CSV file and the link to it in one go. (You need to introduce the concept of a page "mode" and activate the download mode via a ...pagename.php?mode=download or similar. You could then use PHP's switch statement to switch on $_GET['mode'] in your script.)

That said, the text/csv content type header you were using is correct, although you may also want to output the Content-Length and Content-Disposition headers. After you've output the file data, also be sure to stop any additional script processing via PHP's exit function.

Additionally, it would probably be a lot less hassle (and will certainly be faster/more memory efficient) to use MySQL SELECT ... INTO OUTFILE facility (if you have the permissions) rather than use PHP to gather the data.

John Parker
  • 54,048
  • 11
  • 129
  • 129
0

You should not put the link in the same file that generates the csv, as the link will not be in the csv itself!

Do something like:

<a href="fileThatGeneratesTheCSV.php">Download CSV</a>

and it should work

nico
  • 50,859
  • 17
  • 87
  • 112
  • And then use the correct content type: application/vnd.ms-excel with .xls files. – Andrew Sledge Jan 05 '11 at 17:52
  • @Andrew Sledge: Why would you use such content type? What happens if I don't have Office installed? `text/csv` is what he should use. – nico Jan 05 '11 at 17:54
  • I think Andrew Sledge was saying, for the commented out line about xls files, use the proper type. – Andrew Jan 06 '11 at 14:03
0

You can't have text and a download on the same page. You need to have a link to the download area, which could just be a GET parameter leading to a function, which then does all the processing, displays headers, and echoes the content of the CSV.

For example, you could have <a href="foo.php?action=download">Click here to download CSV</a>, then in your code have if ($_GET['action'] === 'download'), get the data from the database, format it, send the headers, and echo the data. And then die(), because that part of the script can accomplish no more.

Andrew
  • 5,095
  • 6
  • 42
  • 48
0

Three things to consider:

  1. You're sending headers indicating that the user is going to be downloading a CSV file, but then you send create a link to download it? This isn't correct, you should be linking to this page, and then only outputting the CSV data itself after the headers.

  2. MySQL has the ability to generate CSV output, and you should definitely take advantage of this instead of trying to do it yourself. You can use SELECT INTO ... OUTFILE to do this.

  3. If you must create the CSV using PHP, please use fputcsv to do so. This will handle all the complications of CSV such as escaping and proper formatting. Since fputcsv writes to a file, you could either write it to a temporary file and then output it after you send your headers, or use the following trick to output it directly:

Do this after sending headers:

$fp = fopen('php://output', 'w');
while( $row = mysql_fetch_row( $export ) ) {
    fputcsv($fp, $row);
}
mfonda
  • 7,873
  • 1
  • 26
  • 30
0

I think the mySQL => CSV is common problem which is part of each PHP forum. I have try to solve this issue in a common way and implement an free export lib for PHP which is very similar to the Google AppInventor philosophie. DragDrop and hide the coding stuff.

Use the lib and create your Export via Click&Point.

Common Demos: http://www.freegroup.de/software/phpBlocks/demo.html Link to editor: http://www.freegroup.de/test/editor/editor.php?xml=demo_sql.xml

worth a look

Greetings

Andreas

Andreas
  • 11
  • 1