I have the below code, where I generate random numbers and try to download them as a CSV file.
If I try the CSV code snippet alone on a different file it works, but in this code, it just does not work. I do see the random numbers echoed, but it does not download the CSV file.
<?php
$dataarray=array();
function convert_to_csv($input_array, $output_file_name, $delimiter)
{
$temp_memory = fopen('php://memory', 'w');
foreach ($input_array as $line)
{
fputcsv($temp_memory, $line, $delimiter);
}
fseek($temp_memory, 0);
header('Content-Type: application/csv');
header('Content-Disposition: attachement; filename="' . $output_file_name . '";');
fpassthru($temp_memory);
}
for ($i = 0; $i <= 25000; $i++)
{
$num = (rand(50,110));
array_push($dataarray,"$num");
echo "Hearbeat #" .$i . "\t\t ------ " . $num;
echo "<br>";
}
convert_to_csv($dataarray, 'data_as_csv.csv', ',');
?>
Outputting data before sending headers with header() means that header() calls will have no effect. So it is reasonable not to send anything before headers.
As another answer mentioned - second argument to fputcsv must be array, so I changed the call to fputcsv too.
If you want all values to written to csv file with comma as separator - pass $input_array directly to fputcsv.
So, your code can look like:
<?php
$dataarray=array();
function convert_to_csv($input_array, $output_file_name, $delimiter)
{
$temp_memory = fopen('php://memory', 'w');
// Option 1 - every number will be on a new line
foreach ($input_array as $line)
{
// add `array($line)` not `$line`
fputcsv($temp_memory, array($line), $delimiter);
}
// Option 2 - all numbers will be in
// one line with `$delimiter` as separator
fputcsv($temp_memory, $input_array, $delimiter);
fseek($temp_memory, 0);
header('Content-Type: application/csv');
header('Content-Disposition: attachement; filename="' . $output_file_name . '";');
fpassthru($temp_memory);
}
for ($i = 0; $i <= 25000; $i++)
{
$num = (rand(50,110));
array_push($dataarray,"$num");
// this two lines are nor needed
//echo "Hearbeat #" .$i . "\t\t ------ " . $num;
//echo "<br>";
}
convert_to_csv($dataarray, 'data_as_csv.csv', ',');
Actually, the problem is in your convert_to_csv function.
fputcsv expects the second parameter to be an array, and in you case is a string. You have 2 options depending on what you want:
1) Each number in a separate line: just change the fputcsv function call to: fputcsv($temp_memory, [$line], $delimiter);
2) All numbers in the same line separated by $delimiter:
function convert_to_csv($input_array, $output_file_name, $delimiter)
{
$temp_memory = fopen('php://memory', 'w');
fputcsv($temp_memory, $fields, $delimiter);
fseek($temp_memory, 0);
header('Content-Type: application/csv');
header('Content-Disposition: attachement; filename="' . $output_file_name . '";');
fpassthru($temp_memory);
}
And (I'm sure you already know), for the file to be downloaded automatically you must not echo anything.
Related
I have a function in PHP that aims to download a csv file, but there is always a blank line at the start of the file
How to delete the blank line at the beginning of the file
this is my code
$name_file = 'ekspor-kag-bri-' . date('Ym', strtotime($data_pendukung['tgl_trf'])) . '.csv';
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="'.$name_file.'"');
$kata_header = "REKENING;NOMINAL;EMAIL"."\n";
$kata_header .= "tes";
$arr_isi_cell = [];
foreach ($dt_gaji as $row) {
$isi_cell = str_replace("-","",$row->norekening) . ';' . floatval($row->total_gaji) . ';' . 'inayohanes#gmail.com'."\n";
array_push($arr_isi_cell,$isi_cell);
}
$myfile = fopen("php://output", "wb");
fwrite($myfile,$kata_header);
foreach($arr_isi_cell as $line){
// fputcsv($myfile,explode(',',$line),",");
fwrite($myfile,$line);
}
fclose($myfile)
I have a query that returns an array which is then processed by this function to ultimately write the output to a csv file. My question is about the path of the output file, it should not be accessible via the web root hence the idea to have the path as /tmp/ instead? Or should I create a new folder specifically for the uploads outside of the web root? So basically I just want to make sure that no one browsing our website, which is pretty much locked down anyway to specific ip's can access the csv files generated by this function. P
$date = date("Y-m-d H:i:s");
$file = $date . ".csv";
function array_to_csv_download($array, $filename, $delimiter = ",")
{
header("Content-Type: application/csv");
header('Content-Disposition: attachment; filename="' . $filename . '";');
$u = "/tmp/" . $filename;
// open the "output" stream
$f = fopen($u, "a");
$csv = array_map("str_getcsv", file($u));
if (isset($csv[0])) {
//do nothing
} else {
//header
$fields = ["Name", "Contact Number"];
fputcsv($f, $fields, $delimiter);
}
//content
foreach ($array as $line) {
//foreach ($array as $header => $line)
fputcsv($f, $line, $delimiter);
}
}
array_to_csv_download($customer_id_result, $file);
P.S. Hope I can post this type of question here, if not please advise on which site part of the group
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.
Im having a problem of exporting my csv. Yes it can export but when it exported the colmun name is included. How can i remove the first row (column name) after i exported?
Tried looking for other solution yet it doesnt fit on my program
<?php
//include database configuration file
include 'config2.php';
//get records from database
$query = $db->query("SELECT * FROM maternalproblem ");
if($query->num_rows > 0){
$delimiter = ",";
$filename = "maternalproblem" . date('Y-m-d') . ".csv";
//create a file pointer
$f = fopen('php://memory', 'w');
//set column headers
$fields = array('MPID', 'district_id', 'barangay_id', 'PID', 'tuberculosis', 'sakit','diyabetes','hika','bisyo');
fputcsv($f, $fields, $delimiter);
//output each row of the data, format =line as csv and write to file pointer
while($row = $query->fetch_assoc()){
$lineData = array($row['MPID'], $row['district_id'], $row['barangay_id'], $row['PID'], $row['tuberculosis'],$row['sakit'],$row['diyabetes'],$row['hika'],$row['bisyo']);
df.to_csv($filename , header=False);
fputcsv($f, $lineData, $delimiter);
}
//move back to beginning of file
fseek($f, 0);
//set headers to download file rather than displayed
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="' . $filename . '";');
//output all remaining data on a file pointer
fpassthru($f);
}
exit;
?>
I just need to export the data and not with the column name. Thank you
It would probably be simpler to just not put the column titles out into the file
So remove these lines
//set column headers
$fields = array('MPID', 'district_id', 'barangay_id', 'PID', 'tuberculosis', 'sakit','diyabetes','hika','bisyo');
fputcsv($f, $fields, $delimiter);
I am a novice programmer and I searched a lot about my question but couldn't find a helpful solution or tutorial about this.
My goal is I have a PHP array and the array elements are showing in a list on the page.
I want to add an option, so that if a user wants, he/she can create a CSV file with array elements and download it.
I don't know how to do this. I have searched a lot too. But yet to find any helpful resource.
Please provide me some tutorial or solution or advice to implement it by myself. As I'm a novice please provide easy to implement solutions.
My array looks like:
Array
(
[0] => Array
(
[fs_id] => 4c524d8abfc6ef3b201f489c
[name] => restaurant
[lat] => 40.702692
[lng] => -74.012869
[address] => new york
[postalCode] =>
[city] => NEW YORK
[state] => ny
[business_type] => BBQ Joint
[url] =>
)
)
You can use the built in fputcsv() for your arrays to generate correct csv lines from your array, so you will have to loop over and collect the lines, like this:
$f = fopen("tmp.csv", "w");
foreach ($array as $line) {
fputcsv($f, $line);
}
To make the browsers offer the "Save as" dialog, you will have to send HTTP headers like this (see more about this header in the rfc):
header('Content-Disposition: attachment; filename="filename.csv";');
Putting it all together:
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);
}
// reset the file pointer to the start of the file
fseek($f, 0);
// tell the browser it's going to be a csv file
header('Content-Type: text/csv');
// tell the browser we want to save it instead of displaying it
header('Content-Disposition: attachment; filename="'.$filename.'";');
// make php send the generated csv lines to the browser
fpassthru($f);
}
And you can use it like this:
array_to_csv_download(array(
array(1,2,3,4), // this array is going to be the first row
array(1,2,3,4)), // this array is going to be the second row
"numbers.csv"
);
Update:
Instead of the php://memory you can also use the php://output for the file descriptor and do away with the seeking and such:
function array_to_csv_download($array, $filename = "export.csv", $delimiter=";") {
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="'.$filename.'";');
// open the "output" stream
// see http://www.php.net/manual/en/wrappers.php.php#refsect2-wrappers.php-unknown-unknown-unknown-descriptioq
$f = fopen('php://output', 'w');
foreach ($array as $line) {
fputcsv($f, $line, $delimiter);
}
}
I don't have enough reputation to reply to #complex857 solution. It works great, but I had to add ; at the end of the Content-Disposition header. Without it the browser adds two dashes at the end of the filename (e.g. instead of "export.csv" the file gets saved as "export.csv--"). Probably it tries to sanitize \r\n at the end of the header line.
Correct line should look like this:
header('Content-Disposition: attachment;filename="'.$filename.'";');
In case when CSV has UTF-8 chars in it, you have to change the encoding to UTF-8 by changing the Content-Type line:
header('Content-Type: application/csv; charset=UTF-8');
Also, I find it more elegant to use rewind() instead of fseek():
rewind($f);
Thanks for your solution!
Try...
csv download.
<?php
mysql_connect('hostname', 'username', 'password');
mysql_select_db('dbname');
$qry = mysql_query("SELECT * FROM tablename");
$data = "";
while($row = mysql_fetch_array($qry)) {
$data .= $row['field1'].",".$row['field2'].",".$row['field3'].",".$row['field4']."\n";
}
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename="filename.csv"');
echo $data; exit();
?>
That is the function that I used for my project, and it works as expected.
function array_csv_download( $array, $filename = "export.csv", $delimiter=";" )
{
header( 'Content-Type: application/csv' );
header( 'Content-Disposition: attachment; filename="' . $filename . '";' );
// clean output buffer
ob_end_clean();
$handle = fopen( 'php://output', 'w' );
// use keys as column titles
fputcsv( $handle, array_keys( $array['0'] ), $delimiter );
foreach ( $array as $value ) {
fputcsv( $handle, $value, $delimiter );
}
fclose( $handle );
// flush buffer
ob_flush();
// use exit to get rid of unexpected output afterward
exit();
}
Use the below code to convert a php array to CSV
<?php
$ROW=db_export_data();//Will return a php array
header("Content-type: application/csv");
header("Content-Disposition: attachment; filename=test.csv");
$fp = fopen('php://output', 'w');
foreach ($ROW as $row) {
fputcsv($fp, $row);
}
fclose($fp);
If you're array structure will always be multi-dimensional in that exact fashion, then we can iterate through the elements like such:
$fh = fopen('somefile.csv', 'w') or die('Cannot open the file');
for( $i=0; $i<count($arr); $i++ ){
$str = implode( ',', $arr[$i] );
fwrite( $fh, $str );
fwrite( $fh, "\n" );
}
fclose($fh);
That's one way to do it ... you could do it manually but this way is quicker and easier to understand and read.
Then you would manage your headers something what complex857 is doing to spit out the file. You could then delete the file using unlink() if you no longer needed it, or you could leave it on the server if you wished.
Update for UTF-8 Encoding
Updating #complex857 's answer
function array_to_csv_download($array, $filename = "export.csv", $delimiter=",") {
header('Content-Disposition: attachment; filename="'.$filename.'";');
header('Content-Type: application/csv; charset=UTF-8');
// open the "output" stream
$f = fopen('php://output', 'w');
// Write utf-8 bom to the file
fputs($f, chr(0xEF) . chr(0xBB) . chr(0xBF));
foreach ($array as $line) {
fputcsv($f, $line, $delimiter);
}
}
May be a bit ugly code but it works!
This function can generate a downloadable CSV file, you can set up the name and the delimiter without tricky functions (UTF-8 encoding in header function).
/**
* Array2CSVDownload
*
*/
function Array2CSVDownload($array, $filename = "export.csv", $delimiter=";") {
// force object to be array, sorry i was working with object items
$keys = array_keys( (array) $array[0] );
// use keys as column titles
$data = [];
array_push($data, implode($delimiter, $keys));
// working with items
foreach ($array as $item) {
$values = array_values((array) $item);
array_push($data, implode($delimiter, $values));
}
// flush buffer
ob_flush();
// mixing items
$csvData = join("\n", $data);
//setup headers to download the file
header('Content-Disposition: attachment; filename="'.$filename.'";');
//setup utf8 encoding
header('Content-Type: application/csv; charset=UTF-8');
// showing the results
die($csvData);
}