Exporting a javascript array as CSV - php

I have a javascript array which i have to save as CSV in client environment..Is that possible using jquery? I have to make in work in all major browsers too..I'm using symfony2 framework..How can this be done if I can pass this array to the server..Please explain the best possible way to pass array as I'm having a pretty large array of associativ arrays..

You can send the data to the server however you'd like (using $_POST, AJAX, etc.). Once the data arrives at the server, though, this is how I would go about sending the data to a CSV file.
$serialized_data = $_POST['some_data_array'];
if($downloadFile) // simple condition
{
$fp = fopen('php://memory', 'w+'); // open up write to memory
foreach($serialized_data as $row) // $serialized_data represents what you sent to the server from JS
{
fputcsv($fp, $row);
}
rewind($fp);
$csvFile = stream_get_contents($fp);
fclose($fp);
header('Content-Type: text/csv');
header('Content-Length: '.strlen($csvFile));
header('Content-Disposition: attachment; filename="yourFile.csv"');
exit($csvFile);
}

Related

Export HTML table to CSV file

I am making a script which gets a table from your mail and puts it into a CSV file.
This is the code I use to transfer my html table to CSV
$html = str_get_html($outputstr);
// For Excel
header('Content-type: application/ms-excel');
// Download File
header('Content-Disposition: attachment; filename=sample.csv');
$fp = fopen("php://output", "w");
// Take out empty lines
foreach($html->find('tr') as $element) {
$td = array();
foreach( $element->find('th') as $row) {
$td [] = $row->plaintext;
}
foreach( $element->find('td') as $row) {
$td [] = $row->plaintext;
}
fputcsv($fp, $td);
}
fclose($fp);
The only problem that I'm getting is that when I am opening the CSV file, some of the empty columns have a strange character:
I cannot read through with my PHP script to export it to a database
fgetcsv($handle, 1000, "\t");
How can I fix this problem?
Do I fix this by modifying the code on the part where I create the CSV file or where I read the CSV file when I'm transferring it to a MySQL database?
When I use an online html to CSV converter it works fine and I am not facing this issue then.
If there is any code needed then I'd love to share it.
Any help would be appreciated.
Have you tried setting your charset to UTF-8? Additionally, you're not setting this up as a CSV with your header, instead it is an Excel file.
header("content-type:application/csv;charset=UTF-8");

Why PHP continue to output to CSV file after fclose()?

On a web page, I am writing some data into a CSV file using the below code and finally closing with fclose();
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename='.$filename);
$out = fopen('php://output', 'w');
fputcsv($out, $cvs_cols);
fclose($out);
echo "HELLO WORLD"; // sneaks into CSV!?
Why is it that "HELLO WORLD" gets into the CSV download file when it has already fclose()? I want to output the rest of the HTML for the page to be displayed in the browser. How can I do that?
After 1 HTTP request follows 1 response. You cannot send content type text/csv and content type text/html at the same time (maybe yes with SPDY, but not with pure HTTP).
fclose closes your file descriptor but not the output to the browser.
You should also set a Content-Length header and put in the filesize.
Mark Baker already gave the most important point in the comments:
echo and writing to php://output puts content into the same stream: STDOUT. Other options would be to write the CSV to memory (but its senseless if you don't use it) or to a file. Read more about the those streams: http://www.php.net/manual/en/features.commandline.io-streams.php
Possible solution:
You need 2 HTTP requests. 1 For the download, the other for your HTML. Most popular way is it to first use the HTML response and put something in like
<meta http-equiv="refresh"
content="3; URL=http://yourserver.com/download.php?id=pdf&id=123" />
This starts the download after 3 seconds.
There is no 'CSV File' (yet).
What you are doing is sending a data stream to the client, and telling the client that this stream has a Content-Type of text/csv and a filename of $filename. The client can then chose to save this as a CSV file or just display it in the browser.
This code:
$out = fopen('php://output', 'w');
fputcsv($out, $cvs_cols);
fclose($out);
Is effectively doing the same thing that echo $cvs_cols would do (with a little extra stuff to format a csv output).
So when there is a call to echo "HELLO WORLD"; it gets sent in the same data steam as the contents of the $cvs_cols variable.
When you call fopen('php://output', 'w') you are creating a second file handle to php://output as one is created by default to output from calls to echo etc. So when you are calling fclose($out) you're only closing the second file handle.
A very old thread here but to fix this I just added a simple exit(); command. So a button calls the same page with a query string of 'action=export_csv' then that action is run with the exit(); on the last line, hope that helps out.
Export CSV
Then the 'action' on the page is:
if(isset($_GET['action']) && $_GET['action']=='export_csv'){
// output headers so that the file is downloaded rather than displayed
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=email-responses.csv');
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
// output the column headings
fputcsv($output, array('Email address'));
$db = new PDO('mysql:host=hostname_mysql;dbname=database_mysql;charset=UTF8', username_mysql, password_mysql);
$query = "SELECT XXX FROM XXXX";
$result = $db->query($query);
$data = $result->fetchAll(PDO::FETCH_ASSOC);
// loop over the rows, outputting them
foreach($data as $row){
fputcsv($output, $row);
}
fclose($output);
exit();
}
use
ob_clean() : ob_clean — Clean (erase) the output buffer
flush() : flush — Flush the output buffer(flush)
ob_start();
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename='.$filename);
$out = fopen('php://output', 'w');
fputcsv($out, $cvs_cols);
fclose($out);
ob_end_clean(); // the buffer and never prints or returns anything.
echo "HELLO WORLD"; // sneaks into CSV!?

reading a large file and forcing download

$name = 'mybigfile.csv';
$fp = fopen(...);
while($row = mysql_fetch_assoc($sql_result)) {
fputcsv($fp, $row);
}
fclose($fp);
// send the correct headers
header("Content-Type: application/csv etc ....");
header("Content-Length: " . filesize($name));
// dump the file and stop the script
readfile($name);
exit;
this method works fine but some of the files are quite big so which makes it quite slow process ... I was thinking - maybe if I could avoid the process of creating a file first and then write data and THEN read the data and output .... .i.e. if I send headers before the while loop and echo line in the while loop (instead of writing it in a line) or something like this. Would this be more efficient process? What would you suggest me to improve this process? thanks
Write directly to the output:
header("Content-Type: application/csv etc ....");
while ($row = mysql_fetch_assoc($sql_result)) {
fputcsv(STDOUT, $row);
}
See here for reference: http://www.php.net/manual/en/wrappers.php.php

How to make fputcsv "echo" the data

I need a way to make the fputscv function write data to the browser on-the-fly instead of creating a temporary file, saving data into that file and doing a echo file_get_contents().
Found this on the PHP docs website, first comment under the function reference:
function outputCSV($data) {
$outstream = fopen("php://output", 'w');
function __outputCSV(&$vals, $key, $filehandler) {
fputcsv($filehandler, $vals, ';', '"');
}
array_walk($data, '__outputCSV', $outstream);
fclose($outstream);
}
And a second option:
$csv = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
fputcsv($csv, array('blah','blah'));
rewind($csv);
// put it all in a variable
$output = stream_get_contents($csv);
Hope this helps!
BTW the PHP docs should always be your first stop when trying to figure things out. :-)
By a comment on the PHP site
<?php
$out = fopen('php://output', 'w');
fputcsv($out, array('this','is some', 'csv "stuff", you know.'));
fclose($out);
?>
As the original asker wanted to "write to the browser on the fly", maybe is worth noting (as was my case and noone mentioned it) that if you want to force a file name and a dialog asking to download a file in the browser, you must set the proper headers before outputting anything with fputcsv:
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=myFile.csv');
Producing a CSV is actually not all that difficult (parsing a CSV is a little bit more involved).
Sample code for writing a 2D Array as CSV:
$array = [
[1,2,3],
[4,5,6],
[7,8,9]
];
// If this CSV is a HTTP response you will need to set the right content type
header("Content-Type: text/csv");
// If you need to force download or set a filename (you can also do this with
// the download attribute in HTML5 instead)
header('Content-Disposition: attachment; filename="example.csv"')
// Column heading row, if required.
echo "Column heading 1,Column heading 2,Column heading 3\n";
foreach ($array as $row) {
$row = array_map(function($cell) {
// Cells containing a quote, a comma or a new line will need to be
// contained in double quotes.
if (preg_match('/["\n,]/', $cell)) {
// double quotes within cells need to be escaped.
return '"' . preg_replace('/"/', '""', $cell) . '"';
}
return $cell;
}, $row);
echo implode(',', $row) . "\n";
}

php how to serialize array of objects?

I have small class called 'Call' and I need to store these calls into a flat file. I've made another class called 'CallStorage' which contains an array where I put these calls into.
My problem is that I would like to store this array to disk so I could later read it back and get the calls from that array.
I've tried to achieve this using serialize() and unserialize() but these seems to act somehow strange and part of the information gets lost.
This is what I'm doing:
//write array to disk
$filename = $path . 'calls-' . $today;
$serialized = serialize($this->array);
$fp = fopen($filename, 'a');
fwrite($fp, $serialized);
fclose($fp);
//read array from serialized file
$filename = $path . 'calls-' . $today;
if (file_exists($filename)) {
$handle = fopen($filename, 'r');
$contents = fread($handle, filesize($filename));
fclose($handle);
$unserialized = unserialize($contents);
$this->setArray($unserialized);
}
Can someone see what I'm doing wrong, or what. I've also tried to serialize and write arrays that contains plain strings. I didn't manage to get that working either.. I have a Java background so I just can't see why I couldn't just write an array to disk if it's serialized. :)
Firstly, use the shorthand forms:
file_put_contents($filepath,serialize($var));
and
$var=unserialize(file_get_contents($filepath));
And then output/debug at each stage to find where the problem is.

Categories