I want to export a table from my database, which contains a column where I put large text content, even many paragraphs. I've tested a script that does this work, but it has a special problem with this large text column. When I run the script and it exports the csv file, large text column just splits when there's a line break, and it takes all these line breaks as new fields inside the file, so csv file just breaks down.
I put my code here. Any ideas would be very appreciated.
<?php
// Database Connection
$host="localhost";
$uname="*****";
$pass="*****";
$database = "****";
$connection=mysql_connect($host,$uname,$pass);
echo mysql_error();
//or die("Database Connection Failed");
$selectdb=mysql_select_db($database) or die("Database could not be selected");
$result=mysql_select_db($database)
or die("database cannot be selected <br>");
// Fetch Record from Database
$output = "";
$table = "table"; // Enter Your Table Name
$sql = mysql_query("SELECT * FROM $table");
$columns_total = mysql_num_fields($sql);
// Get The Field Name
for ($i = 0; $i < $columns_total; $i++) {
$heading = mysql_field_name($sql, $i);
$output .= '"'.$heading.'",';
}
$output .="\n";
// Get Records from the table
while ($row = mysql_fetch_array($sql)) {
for ($i = 0; $i < $columns_total; $i++) {
$output .='"'.$row["$i"].'",';
}
$output .="\n";
}
// Download the file
$filename = "file.csv";
header('Content-type: application/csv');
header('Content-Disposition: attachment; filename='.$filename);
echo $output;
exit;
?>
Since you're using mysql_*, I'm not going to edit that code, since the library is deprecated. You can use my personal code here which uses PDO.
<?php
include 'dbconnector.php';
$array = array();
# Headers
$array[] = array("header1", "header2");
$serial=1;
try
{
$s = $conn->query("Query Here");
}
catch(PDOException $e)
{
echo $e->getMessage();
}
while($donations = $s->fetch(PDO::FETCH_OBJ))
{
$array[] = array("column1","column2");
}
array_to_csv_download($array,"records.csv",",");
function array_to_csv_download($array, $filename = "export.csv", $delimiter=";") {
// open raw memory as file so no temp files needed, you might run out of memory though
$f = fopen('php://memory', 'w');
// loop over the input array
foreach ($array as $line) {
// generate csv lines from the inner arrays
fputcsv($f, $line, $delimiter);
}
// rewrind the "file" with the csv lines
fseek($f, 0);
// tell the browser it's going to be a csv file
header('Content-Type: application/csv');
// tell the browser we want to save it instead of displaying it
header('Content-Disposition: attachement; filename="'.$filename.'";');
// make php send the generated csv lines to the browser
fpassthru($f);
}
?>
Related
I have 2 options, one to download all entries of a database; The second option to download only selected values (in a table, passed as array); both options download the entries in a file .txt one per line.
But, sometimes and only on certain lines, the result is messed up, and no new line is created.
Is there any idea on what could cause this?
That's the code for download:
function DownloadAll() {
//DOWNLOAD ALL DATAS
$sql = $conn->prepare($query);
$sql->bind_param('i', $userid);
$sql->execute();
$res = $sql->get_result();
while ($ext = $res->fetch_assoc()) {
$file = fopen('/home/tmp/'.$varr.'_export.txt', "a");
if( strpos(file_get_contents('/home/tmp/'.$varr.'_export.txt'),$ext['account_name']) !== true)
{
$content = $ext['id'];
$content .= ":";
$content .= $ext['name'];
$content .= ":";
$content .= $ext['code'];
fwrite($file, $content);
fclose($file);
} else { fclose($file); }
}
}
function DownloadArray($data) {
//DOWNLOAD FROM SELECTED ROWS ARRAY
foreach($data as $do)
{
$sql = $conn->prepare($query);
$sql->bind_param('ii', $userid, $do);
$sql->execute();
$sql->bind_result($id, $name, $code);
$sql->fetch();
$sql->close();
$file = fopen('/home/tmp/'.$varr.'_export.txt', "a");
if( strpos(file_get_contents('/home/tmp/'.$varr.'_export.txt'),$name) !== true) {
$content = $id;
$content .= ":";
$content .= $name;
$content .= ":";
$content .= $code;
fwrite($file, $content);
fclose($file);
} else { fclose($file); }
}
}
function export() {
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($varr.'_export.txt'));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize('/home/tmp/'.$varr.'_export.txt'));
readfile('/home/tmp/'.$varr.'_export.txt');
sleep(1);
unlink('/home/tmp/'.$varr.'_export.txt');
die();
}
And that is an example output (found in the .txt file) with the problem
1:vanne:tsvC2:rika:rgPrp3nierde:9K9g4:Caize:vW5g
5:lina:CZPr6:niki:phv47:hery:sh2u
8:shave:4xRj
9:riuster:S74W
10:bunn:vfH9
11:kei:t8vT
12:phas:R3kK
13:nelyn:Bw14:nedah:JtKu
15:rosi:Tfz4
16:seaur:mDY8
17:andrey:QSAA
18:taled:Tba519:evang:yedM20:taver:qs6n
As you see, some lines are all messed up, it doesn't create a new line and it just put the text right after the last one.
It doesn't happen randomly, only to specific lines with specific content or something, because if I download the same export multiple times, it won't be randomly messed up, all lines are messed up identically on all files.
EDIT
The problem was in the fwrite option not adding the new lines.
fwrite($file, $content.PHP_EOL);
Fixed it.
fwrite() is a binary-safe file write. It doesn't add a new line, and neither does your code.
The newlines you see must be coming from the data in your database.
Add a newline to each line:
fwrite($file, $content.PHP_EOL);
And ensure that your data doesn't have them.
I have this code
$dateFile = "data.txt";
$data = $this->Setting->Loop("data");
foreach($data->result() as $dat){
$dataString = "USERNAME| ".$dat->user." / DATA| ".$dat->values_text.".\n";
file_put_contents($dateFile,$dataString);
}
header('Content-Type: application/text');
header('Content-Disposition: attachment; filename="'.$dateFile);
echo file_get_contents($dateFile);
which get data from table data and insert it into file called data.txt with this format
USERNAME| qwq / DATA| www.
My problem is that the code take just one record of data because the data stored in a single string, how can I make it get all records?
Edit #1
I found a solution and this is the new working code
$dateFile = "data.txt";
$data = $this->Setting->Loop("data");
$dataContent = array();
$i = 0;
foreach($data->result() as $dat){
$i++;
$dataContent[$i] = "USERNAME| ".$dat->user." / DATA| ".$dat->values_text.".\n";
}
file_put_contents($dateFile,$dataContent);
header('Content-Type: application/text');
header('Content-Disposition: attachment; filename="'.$dateFile);
echo file_get_contents($dateFile);
Try this code:
$filename = __dir__.'test.php';
$data = 'This is sample text';
fopen($filename, 'w') or die('Cannot open file: '.$filename);
fwrite($handle, $data);
Hope this will help you
So I have this code to generate a CSV file from mysql database. But however, it downloads the code instead of saving it to the directory for further use (need to send that file via phpmailer).
What changes should I do to make it save the file to the directory.
$array = array();
if(file_exists('records_monthly.csv'))
{
unlink('records_monthly.csv');
}
# Headers
$array[] = array("Serial Number","Donation Type", "Amount", "Status", "Date", "Orderref", "DIN");
$serial=1;
try
{
$s = $conn->query("SELECT c.firstname AS firstname, c.lastname as lastname, c.address AS address, c.city AS city, c.postalnumber AS postalnumber, c.email AS cemail, d.donation_type as donation_type, d.donation_amount as donation_amount, d.orderref as orderref, d.status as status, d.donation_on AS donation_on, d.din as din from customers c, donations d where c.email = d.donator");
}
catch(PDOException $e)
{
echo $e->getMessage();
}
while($donations = $s->fetch(PDO::FETCH_OBJ))
{
if($donations->status == 0)
{
$array[] = array($serial++,$donations->donation_type,$donations->donation_amount,"Failed",$donations->donation_on,$donations->orderref,$donations->din);
}
else
{
$array[] = array($serial++,$donations->donation_type,$donations->donation_amount,"Success",$donations->donation_on,$donations->orderref,$donations->din);
}
}
array_to_csv_download($array,"records_monthly.csv",",");
function array_to_csv_download($array, $filename = "export.csv", $delimiter=";") {
// open raw memory as file so no temp files needed, you might run out of memory though
$f = fopen('php://memory', 'w');
// loop over the input array
foreach ($array as $line) {
// generate csv lines from the inner arrays
fputcsv($f, $line, $delimiter);
}
// rewind the "file" with the csv lines
fseek($f, 0);
// tell the browser it's going to be a csv file
header('Content-Type: application/csv');
// tell the browser we want to save it instead of displaying it
header('Content-Disposition: attachement; filename="'.$filename.'";');
// make php send the generated csv lines to the browser
fpassthru($f);
}
Write directly to the named file rather than to php://memory and don't send headers and output to the browser
function array_to_csv_without_download($array, $filename = "export.csv", $delimiter=";") {
$f = fopen($filename, 'w');
// loop over the input array
foreach ($array as $line) {
// generate csv lines from the inner arrays
fputcsv($f, $line, $delimiter);
}
fclose($f);
}
So my following code generated a CSV based on specified tables and generates file and saves to downloads/filename.csv however its not asking the user to download once its generated. Any ideas why?
Here is the code:
PHP
header("Content-type: text/csv");
// Connect to the database
$mysqli = new mysqli(DATABASE_HOST, DATABASE_USER, DATABASE_PASS, DATABASE_NAME);
// output any connection error
if ($mysqli->connect_error) {
die('Error : ('.$mysqli->connect_errno .') '. $mysqli->connect_error);
}
$tables = array('invoices', 'customers', 'invoice_items'); // array of tables need to export
$file_name = 'invoice-export-'.date('d-m-Y').'.csv'; // file name
$file_path = 'downloads/'.$file_name; // file path
$file = fopen($file_path, "w"); // open a file in write mode
chmod($file_path, 0777); // set the file permission
// loop for tables
foreach($tables as $table) {
$table_column = array();
$query_table_columns = "SHOW COLUMNS FROM $table";
// fetch table field names
if ($result_column = mysqli_query($mysqli, $query_table_columns)) {
while ($column = $result_column->fetch_row()) {
$table_column[] = $column[0];
}
}
// Format array as CSV and write to file pointer
fputcsv($file, $table_column, ",", '"');
$query_table_columns_data = "SELECT * FROM $table";
if ($result_column_data = mysqli_query($mysqli, $query_table_columns_data)) {
// fetch table fields data
while ($column_data = $result_column_data->fetch_row()) {
$table_column_data = array();
foreach($column_data as $data) {
$table_column_data[] = $data;
}
// Format array as CSV and write to file pointer
fputcsv($file, $table_column_data, ",", '"');
}
}
}
// close file pointer
fclose($file);
// ask either save or open
header("Pragma: public");
header("Expires: 0");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename='{$file_name}';" );
header("Content-Transfer-Encoding: binary");
// open a saved file to read data
$fhandle = fopen($file_path, 'r');
fpassthru($fhandle);
fclose($fhandle);
$mysqli->close();
die;
This should allow you to select the field you want to write to the CSV file, and their order.
// loop over the rows, outputting them
while($row = $results->fetch_assoc()) {
$data = [
$row["myfirstfield]",
$row["mysecondfield"],
....
];
fputcsv($output, $data);
}
I have the following script that will export data from my database using php to csv file. Everything works fine, except when I try to open the file in excel, I get "file is corrupt". When I run this code it shows the error - "The file is corrupted and can not be opened." Thanks in advance!
<?php
// Connection
include_once('conn.php');
$sql = "select * from info";
$qur = mysql_query($sql);
// Enable to download this file
$filename = "sampledata.csv";
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Type: text/csv");
$display = fopen("php://output", 'w');
$flag = false;
while($row = mysql_fetch_assoc($qur)) {
if(!$flag) {
// display field/column names as first row
fputcsv($display, array_keys($row), ",", '"');
$flag = true;
}
fputcsv($display, array_values($row), ",", '"');
}
fclose($display);
exit;
?>
I found the answer of my own question. Just need to add the ob_clean() line before we call the headers to download csv file to clear the output buffer. This will solve the error of not opening csv file in excel.