I have PHP code that runs a query in a database, saves the results to a csv file, and then allows the user to upload the file. The problem is that the csv file contains an HTML page around the actual csv content.
I already read all the related questions, including this one . Unfortunately, my code exists in Joomla, so even if I try to redirect to a page that contains only headings, Joomla automatically surrounds it with its own navigation code. This only happens at boot time; if I look at the csv file that was saved on the server, it does not contain HTML.
Can someone help me to force the actual CSV file to be downloaded as it is on the server, and not how the browser edits it? I tried using the header location, for example:
header('Location: ' . $filename);
but it opens the file in the browser, and does not format the save dialog.
Here is my current code:
//set dynamic filename $filename = "customers.csv"; //open file to write csv $fp = fopen($filename, 'w'); //get all data $query = "select c.firstname,c.lastname,c.email as customer_email, a.email as address_email,c.phone as customer_phone, a.phone as address_phone, a.company,a.address1,a.address2,a.city,a.state,a.zip, c.last_signin from {$dbpre}customers c left join {$dbpre}customers_addresses a on c.id = a.customer_id order by c.last_signin desc"; $votes = mysql_query($query) or die ("File: " . __FILE__ . "<br />Line: " . __LINE__ . "<p>{$query}<p>" . mysql_error()); $counter = 1; while ($row = mysql_fetch_array($votes,1)) { //put header row if ($counter == 1){ $headerRow = array(); foreach ($row as $key => $val) $headerRow[] = $key; fputcsv($fp, $headerRow); } //put data row fputcsv($fp, $row); $counter++; } //close file fclose($fp); //redirect to file header("Content-type: application/octet-stream"); header("Content-Disposition: attachment; filename=".$filename); header("Content-Transfer-Encoding: binary"); readfile($filename); exit;
edits The full URL is as follows:
http:
with the actual download link looking like this:
http://mysite.com/administrator/index.php?option=com_eimcart&task=customers&subtask=export
MORE EDITING Here is a snapshot of the page on which the code is located; the generated file still draws in html for the submenu. Code for selected link (Export as CSV) now
index.php?option=com_eimcart&task=customers&subtask=export&format=raw

Now here is a screenshot of the generated, saved file:

It is shortened during loading here, but the text highlighted in yellow is the html code for subnav (list of clients, add a new client, export as csv). This is what my complete code looks like now; if I could just get rid of this last html snippet, that would be great.
$fp= fopen("php://output", 'w'); $query = "select c.firstname,c.lastname,c.email as customer_email, a.email as address_email,c.phone as customer_phone, a.phone as address_phone, a.company, a.address1, a.address2,a.city,a.state,a.zip,c.last_signin from {$dbpre}customers c left join {$dbpre}customers_addresses a on c.id = a.customer_id order by c.last_signin desc"; $votes = mysql_query($query) or die ("File: " . __FILE__ . "<br />Line: " . __LINE__ . "<p>{$query}<p>" . mysql_error()); $counter = 1; //redirect to file header("Content-type: application/octet-stream"); header("Content-Disposition: attachment; filename=customers.csv"); header("Content-Transfer-Encoding: binary"); while ($row = mysql_fetch_array($votes,1)) { //put header row if ($counter == 1){ $headerRow = array(); foreach ($row as $key => $val) $headerRow[] = $key; fputcsv($fp, $headerRow); } //put data row fputcsv($fp, $row); $counter++; } //close file fclose($fp);
UPDATE FOR BJORN
Here is the code (I think) that worked for me. Use the RAW parameter in the link that invokes the action:
index.php?option=com_eimcart&task=customers&subtask=export&format=raw
Since this was procedural, our link was in the customer.php file, which looks like this:
switch ($r['subtask']){ case 'add': case 'edit': //if the form is submitted then go to validation include("subnav.php"); if ($r['custFormSubmitted'] == "true") include("validate.php"); else include("showForm.php"); break; case 'delete': include("subnav.php"); include("process.php"); break; case 'resetpass': include("subnav.php"); include("resetpassword"); break; case 'export': include("export_csv.php"); break; default: include("subnav.php"); include("list.php"); break; }
So, when the user clicked on the link above, the export_csv.php file is automatically included. This file contains all the actual code:
<? header("Content-type: application/octet-stream"); header("Content-Disposition: attachment; filename=customers.csv"); header("Content-Transfer-Encoding: binary"); $fp= fopen("php://output", 'w'); //get all data $query = "select c.firstname,c.lastname,c.email as customer_email, a.email as address_email,c.phone as customer_phone, a.phone as address_phone, a.company,a.address1,a.address2,a.city,a.state,a.zip, c.last_signin from {$dbpre}customers c left join {$dbpre}customers_addresses a on c.id = a.customer_id order by c.last_signin desc"; $votes = mysql_query($query) or die ("File: " . __FILE__ . "<br />Line: " . __LINE__ . "<p>{$query}<p>" . mysql_error()); $counter = 1; while ($row = mysql_fetch_array($votes,1)) { //put header row if ($counter == 1){ $headerRow = array(); foreach ($row as $key => $val) $headerRow[] = $key; fputcsv($fp, $headerRow); } //put data row fputcsv($fp, $row); $counter++; } //close file fclose($fp);