user2302780
user2302780

Reputation: 1249

How to create and download a csv file from php script?

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] => 
        )

)

Upvotes: 123

Views: 374490

Answers (9)

Malkhazi Dartsmelidze
Malkhazi Dartsmelidze

Reputation: 4992

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!

Upvotes: 4

Kamran  Gasimov
Kamran Gasimov

Reputation: 1793

THIS IS THE ULTIMATE UTF-8 COMPATIBLE - array to csv function in PHP 100%

 /**
   * array_to_csv_download
   * 
   */
  function array_to_csv_download($array, $filename = "export.csv", $delimiter = ",")
  {
    header('Content-Type: application/csv; charset=UTF-8');
    header('Content-Disposition: attachment; filename="' . $filename . '";');


    // clean output buffer
    ob_end_clean();

    $handle = fopen('php://output', 'w');


    // Write utf-8 bom to the file
    fputs($handle, chr(0xEF) . chr(0xBB) . chr(0xBF));

    // 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();
  } 

Upvotes: 1

Watash1
Watash1

Reputation: 350

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);

}   

Upvotes: 2

Sajidur Rahman
Sajidur Rahman

Reputation: 3060

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();
}

Upvotes: 26

complex857
complex857

Reputation: 20753

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);
    }
}   

Upvotes: 260

Indrajeet Singh
Indrajeet Singh

Reputation: 2989

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();
?>

Upvotes: 19

Kiran Reddy
Kiran Reddy

Reputation: 764

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);

Upvotes: 9

Luxian
Luxian

Reputation: 676

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!

Upvotes: 21

half-fast
half-fast

Reputation: 302

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.

Upvotes: 3

Related Questions