Could not download CSV file on browser using PHP and MySQL - php

I need to download the mysql record to csv file on browser but as per my code it's not working as expected. Here is my code:
$scope.downloadAllCustomerData=function(){
var url2='../service/admin/customer/customer.php?action=downloadAllCustomerData';
var method='GET';
var data1='';
DataService.connectToServerSideScript(method,url2,data1)
.then(function(response) {
console.log('response',response);
},function(error) {
})
}
Here is my client side code which making request to sevre to download the .CSV file.
if ($_REQUEST["action"]=="downloadAllCustomerData") {
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=data.csv');
$output = fopen("php://output", "w");
fputcsv($output, array('ID', 'Name', 'Email', 'MObile No'));
$sql = "SELECT user_id,name,email,mobile from cb_customer_info ORDER BY user_id DESC";
$stmt = $db->prepare($sql);
if ($stmt->execute()) {
$row = $stmt->fetchAll();
$number_of_rows= count($row);
if ($number_of_rows > 0) {
fputcsv($output, $row);
$data=array("status"=>1,"msg"=>"Downloaded all data successfully.");
}else{
$data=array("status"=>0,"msg"=>"No record found.");
}
fclose($output);
}
echo json_encode($data);
}
Here I am trying to download the mysql record into .csv file. I need when user will click on the button those record will be downloaded on the browser.

Better to form data and echo/print to browser instead of using php://output stream.
Usual headers for Download,
header("Content-Disposition: attachment;filename=\"".$file_name."\"");
header('Content-Type: '.$content_type);
header("Accept-Ranges: bytes");
header("Pragma: private");
header("Expires: -1");
header("Cache-Control: private, must-revalidate, post-check=0, pre-check=0");
header("Content-Length: ".$filesize);

Related

PHP: PDO + CSV export not downloading (headers issue?)

I'm having a hard time making my CSV export function work.
I've found around plenty of examples using mysqli_* functions, but I'm actually using PDOs so I had to adapt some questions/answers to my needs.
From what I can see, I'm properly parsing and writing data to the *.csv file, but at the end I don't simply get any "Download" modal from the browser.
Again, looking around, I've understood I may have some kind of problem with my headers, so I'm asking for your help.
This is my PHP function snippet:
function downloadAsCSV($dsn, $dbUser, $dbPsw, $options) {
// New PDO connection.
$pdo = pdoConnect($dsn, $dbUser, $dbPsw, $options);
$query = ... // Not going to write it down.
// Let's query the database, ...
$stmt = $pdo->prepare($query);
// Setting up the query variables here...
[...]
// Executing the statement...
$stmt->execute();
// Headers.
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Description: File Transfer');
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename='export.csv'");
header("Pragma: no-cache");
header("Expires: 0");
// Let's open tbe "*.csv" file where we'll save the results.
$fp = fopen("php://output", "w");
if ($fp) {
$first_row = $stmt->fetch(PDO::FETCH_ASSOC);
$headers = array_keys($first_row);
fputcsv($fp, array_values($first_row));
fputcsv($fp, $headers);
// ... fetch the results...
$workpiecesArray = $stmt->fetchAll();
// ... and, finally, export them.
foreach ($workpiecesArray as $workpiece) {
fputcsv($fp, array_values($workpiece));
}
}
fclose($fp);
// Closing the connection.
$stmt = null;
$pdo = null;
}
function mysqli_field_name($result, $field_offset) {
$properties = mysqli_fetch_field_direct($result, $field_offset);
return is_object($properties) ? $properties->name : null;
}
I've taken inspiration to write the table column titles from this answer.
What you need to do is to print the file, which you're not doing right now.
See this example using readfile:
http://php.net/manual/en/function.header.php#example-5554
Simply put:
1.Replace
$fp = fopen("php://output", "w");
with
$tmpfname = tempnam("/", "");
$fp = fopen($tmpfname, "w");
2.Replace
fclose($fp);
with
fclose($fp);
readfile($tmpfname);
unlink($tmpfname);
and this will work
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="export.csv"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize('export.csv'));
readfile($csvFile);
exit;
`put this after` fclose($fp);

Wordpress converting array to csv for download

I have the following function that takes an array of results from a database query. I populate the array as I loop through the query results. At the same time I create an html table. After outputting the html table I call the function download_csv($csvArray) but no downloading of the CSV happens, It just displays the contents of the the array as if I did a var_dump on the array. I can confirm that the contents of the array are correct.
Note: this is being done on an external web page not from the admin area.
Is there some wordpress function that needs to be called to allow the download or am I missing something?
function download_csv($csvArray) {
$file_name = 'report.csv';
//output headers so that the file is downloaded rather than displayed
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=$file_name");
//Disable caching - HTTP 1.1
header("Cache-Control: no-cache, no-store, must-revalidate");
//Disable caching - HTTP 1.0
header("Pragma: no-cache");
//Disable caching - Proxies
header("Expires: 0");
//Start the ouput
$output = fopen("php://output", "w");
//Then loop through the rows
foreach ($csvArray as $fields) {
fputcsv($output, $fields);
}
//Close the stream off
fclose($output);
die();
}
Following Code will help you to convert Array to CSV and Make it to automatically download Change the die(); function to exit(); And Use Implode function. It will work.
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename=sample.csv');
header('Pragma: no-cache');
header('Expires: 0');
$fp = fopen('php://output', 'w');
//ex: $list={...};
foreach ($list as $fields)
{
fputcsv($fp,implode($fields, ','));
}
fclose($fp);
exit();

Create and download CSV file in one script [duplicate]

This question already has answers here:
Create a CSV File for a user in PHP
(20 answers)
Closed 8 years ago.
I want to create and download a CSV file, in one script.
Up to now I have been avoiding my lack of knowledge by pre-creating the file with a cron job and then
downloading the file via a link.
I have this:
$conn = new mysqli($dbhost, $dbuser, $dbpass, $dbname) or die ('Error connecting to mysql');
$get_members_csv_query = "SELECT * FROM members";
$get_members_csv_result=$conn->query($get_members_csv_query, MYSQLI_STORE_RESULT);
$all_members_array = array();
while ($get_members_csv_array = $get_members_csv_result->fetch_assoc())
{
array_push($all_members_array, $get_members_csv_array);
}
$file = fopen('members.csv', 'w');
fputcsv($file, array('email', 'First Name', 'Surname', 'Gender','DOB','Registered On','Country','paid','Children','Wants Kids','Relationship','Body Type','Height','Smoke','Drink','Phone','Region','Religion','Community'));
foreach ($all_members_array as $row) {
fputcsv($file, $row);
}
exit();
This creates the file successfully, but what do I need to add to the script to make it automatically download the CSV file once created?
I have tried putting this at the start if the script:
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=members.csv");
header("Pragma: no-cache");
header("Expires: 0");
But it downloads the file before the script finishes (or even starts) creating the file.
I have tries putting the headers at the end of the script and using ob_start() at the top - same result.
Thanks
You're never sending the contents of the file to the browser. It should be:
$file = fopen('members.csv', 'w');
fputcsv($file, array('email', 'First Name', 'Surname', 'Gender','DOB','Registered On','Country','paid','Children','Wants Kids','Relationship','Body Type','Height','Smoke','Drink','Phone','Region','Religion','Community'));
foreach ($all_members_array as $row) {
fputcsv($file, $row);
}
fclose($file);
// Download file
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=members.csv");
header("Pragma: no-cache");
header("Expires: 0");
readfile('members.csv');
exit();
Try this:
From the exit() line, modify to:
exit(dnl("members.csv"));//call dnl function
then on the same page write the dnl function:
function dnl($fn){
// Send Header
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");;
header("Content-Disposition: attachment;filename=$fn");
header("Content-Transfer-Encoding: binary ");
}
Remember that the content-type "application/octet-stream" can be changed to match only csv as you have done before.

PHP/MYSQL to CSV Export code printing to screen instead of CSV file

I can't get the browser to prompt for download. The output gets displayed on the screen instead. I've tried so many other threads regarding this topic on this site but to no avail. I could change the fopen("php://output","w") to fopen("export.csv","w") but that will save a copy of the export.csv file on the server, which I don't want. I want the file to be downloaded on the client without it being saved on the server. Here's my code:
$sql = mysql_query($_SESSION["export-query"]);
$fields = mysql_num_fields($sql);
$header = array();
for ($i = 0; $i < $fields; $i++) {
$header[] = mysql_field_name($sql, $i);
}
$f = fopen("php://output","w");
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename=export.csv');
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate');
fputcsv($f, $header);
while ($row = mysql_fetch_row($sql)) {
fputcsv($f, $row);
}
fclose($f);
Please help! Much appreciated.
Your code is really close to mine, but I have this
header("Content-type: application/vnd.ms-excel");
for the content type. I think this works because browsers know how to handle text/csv but they don't know how to handle excel. It will prompt to download because it doesn't open this type of file itself.
I also don't have "must-revalidate," but I don't think that makes a difference.
EDIT:
Here are my full headers, which have worked 100% of the time. There are minor differences from yours, so maybe one of them is the reason.
header("Content-type: application/vnd.ms-excel");
header("Content-disposition: attachment; filename=".$filename.".csv");
header("Pragma: no-cache");
header("Expires: 0");
EDIT 2:
Judging from your comment on your answer, you are putting all of this code as an ajax call inside a div. The reason that doesn't work is that you can only set headers on the initial call to a page. Setting headers on an ajax call will be ignored.
Here is how my system handles csv generation. Because I needed specific information that could vary between different csv files, I put the name of the generator file into the "action" of a form and provided a submit button:
<form action="thegeneratorpage.php" method="get"><fieldset>
<p>Download [...] in .csv (Excel) form. You can narrow by [...].</p>
<!-- code here that allows users to narrow down what is in the csv -->
<input type="submit" value="Download" />
</fieldset></form>
If the information doesn't vary, you can just do this:
Download CSV
All the code we have been discussing would be on thegeneratorpage.php.
Rather than using the fputcsv function, I would suggest just echoing the rows of the CSV file like so (note that the headers I use are slightly different from yours):
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename={$fileName}");
header("Content-Transfer-Encoding: binary");
while ($row = mysql_fetch_row($sql)) {
// optionally enclose data if necessary
foreach ($row as $k => $v) {
if (strpos($v, ',') !== false) {
$row[$k] = '"' . $v . '"';
}
}
echo implode(',', array_values($row));
}

export mysql tables in CVS into a ZIP file

I have done a script in PHP to export a MySQL table into a CVS file when clicking a button. It's working fine but now I need to export 1 table per CSV file, all this in a ZIP (or RAR) file when clicking a button.
Basically it should be:
Export table:
mytable.csv
Export all tables:
export.ZIP containing:
--mytable1.csv
--mytable2.csv
--mytable3.csv
I could loop the export function for each table but that will not put everyting into the ZIP:
/* EXPORT ALL TABLES */
if (isset($_POST['export_all_tables'])){
$Qlist_table = $pdo->prepare('SHOW TABLES');
$Qlist_table->execute(array(''));
foreach ($Qlist_table as $Alist_table)
export_table($Alist_table[0]);
}
function export_table($table_to_export){
$Qselect = $pdo->prepare('SELECT * FROM '.$table_to_export.'');
$Qselect->execute(array(''));
$results = $Qselect->fetchAll(PDO::FETCH_ASSOC);
...
...
...
header("Content-disposition: attachment; filename=".$fileName);
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: application/vnd.ms-excel\n");
header("Pragma: no-cache");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0, public");
header("Expires: 0");
echo $outputCsv;
exit();
}
I don't think you need all the code of the export function, if yes let me know.
Thanks!
Actually I found the solution thanks to addFile(). Here is the code:
if (isset($_POST['export_all_tables'])){
// Name of the file to export
$date = date('Y_m_j_H\hi');
$fileName = 'Export_all_'.$date.'.zip';
// Headers to create the ZIP file
header("Content-disposition: attachment; filename=".$fileName);
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: application/zip;\n");
header("Pragma: no-cache");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0, public");
header("Expires: 0");
// We create the ZIP file
$zip = new ZipArchive;
$result_zip = $zip->open($fileName, ZipArchive::CREATE); // We open the file
if ($result_zip === TRUE) {
$Qlist_table = $pdo->prepare('SHOW TABLES');
$Qlist_table->execute(array(''));
// For each table
foreach ($Qlist_table as $Alist_table) {
$content = export_table($Alist_table[0]);
$fileName = $Alist_table[0].'_'.$date.'.csv';
$zip->addFile($fileName, $fileName); // We add the CSV file from the server
}
$zip->close();
}
else {
echo 'Failed, code:' . $result_zip;
}
readfile("Export_all.zip"); // To download the ZIP file
exit();
}
and the exporttable function ends like that to write the file on the server:
$fh = fopen($fileName, 'w') or die("Can't open file");
$stringData = $outputCsv; // outputCsv is the content of the table
fwrite($fh, $stringData);
fclose($fh);

Categories