wordpress csv export includes html in the output

I am trying to dynamically create a downloadable csv file from within WordPress. The data to be included is correct, and the file is created for download successfully. However, the created csv file includes the template HTML output.

How can the data be output, without the HTML from the template?

Read More

Here is the function. The arrays are correctly populated with a sql query, but the results are identical to this.

function exportAsCSV (  ) {
  $csv = '';
  $header_array = array('Header 1', 'Header 2', 'Header 3');
  $data_array = array(
    array('Row 1 A', 'Row 1 B', 'Row 1 C'),
    array('Row 2 A', 'Row 2 B', 'Row 2 C'), 
  ); 

  $csv .= implode(', ', $header_array);
  $csv .= 'n';

  foreach($data_array as $row){
    $csv .= implode(', ', $row);
    $csv .= 'n';  
  } 


    $now = gmdate('D, d M Y H:i:s') . ' GMT';

    header('Content-Type: text/csv');
    header('Expires: ' . $now);

    header('Content-Disposition: attachment; filename="data.csv"');
    header('Pragma: no-cache'); 

    echo $csv; 
    exit();
}

The function is called as so:

if(isset($_GET['export_data'])){
  ob_end_clean();   
  exportAsCSV();
} 

Related posts

Leave a Reply

2 comments

  1. To make this safer, you could clear the output buffer before sending anything to it.
    After that, you can start sending data to the output buffer, and flush it before closing the data stream. Something like this:

        function get_csv($columns_headers, $data) {
            
            $filename = "php://output";
    
            ob_clean(); //empty the output buffer 
            ob_start();  //and start a new one
            
            header('Pragma: public');
            header('Expires: 0' );
            header('Cache-Control: no-cache, must-revalidate');
            header('Content-Type: text/csv');
            header('Content-Disposition: attachment; filename="'.'data.csv"');
    
            $outstream = fopen($filename, 'r+')  or die("Error opening php://output");
            
            fputcsv( $outstream , $columns_headers );
    
            foreach($data as $item)
                fputcsv($outstream,$item);
            
            ob_flush();  //send the whole buffer
            fclose($outstream) or die("Error closing php://output");    
            //all done
            die();
    
        }
    
  2. I figured it out. More levels of output buffering. Now, I call ob_get_level() to determine how many times to ob_end_clean(). No more extra HTML in the output.