CSV file generation failing

I’m using a plugin for a client (that i modified to some degree) that creates and maintains a database of organization members (using a new wp table to do so).

There is a nice feature that does a csv import and insert, that works great. There is also a feature to download the contents of this table as a csv, that works fine on my local system, but fails when running from the server. I’m, frankly, at a loss as to why.

Read More

The php file that contains the logic is simply linked to. The file:

<?php
    //include some files
    include('../../../wp-blog-header.php');

    //DIAG: phpinfo();   

    function fputcsv4($fh, $arr) {
        $csv = "";
        while (list($key, $val) = each($arr)) {
            $val = str_replace('"', '""', $val);
            $csv .= '"'.$val.'",';
        }
        $csv = substr($csv, 0, -1);
        $csv .= "n";
        if (!@fwrite($fh, $csv)) 
            return FALSE;
    }

    //get member info and column data
    $table_name = $wpdb->prefix . "member_db";
    $year = date ('Y');
    $members = $wpdb->get_results("SELECT * FROM ".$table_name, ARRAY_A);
    $columns = $wpdb->get_results("SHOW COLUMNS FROM ".$table_name, ARRAY_A);
    //DIAG: echo 'SQL: '.$sql.', RESULT: '.$result.'<br>';

    //output headers
    header("Content-type: application/octet-stream");
    header("Content-Disposition: attachment; filename="members.csv"");

    //open output stream
    $output = fopen("php://output",'w'); 

    //output column headings
    $data[0] = "ID";
    $i = 1;
    foreach ($columns as $column){
        //DIAG: echo '<pre>'; print_r($column); echo '</pre>';
        $field_name = '';
        $words = explode("_", $column['Field']);
        foreach ($words as $word) $field_name .= $word.' ';
        if ( $column['Field'] != 'id' && $column['Field'] != 'date_updated' ) {
            $data[$i] = ucwords($field_name);
            $i++;
        }
    }
    $data[$i] = "Date Updated";
    fputcsv4($output, $data);

    //output data
    foreach ($members as $member){
        //DIAG: echo '<pre>'; print_r($member); echo '</pre>';
        $data[0] = $member['id'];
        $i = 1;
        foreach ($columns as $column){
            //DIAG: echo '<pre>'; print_r($column); echo '</pre>';
            if ( $column['Field'] != 'id' && $column['Field'] != 'date_updated' ) {
                $data[$i] = $member[$column['Field']];
                $i++;
            }
        }
        $data[$i] = $member['date_updated'];
        //echo '<pre>'; print_r($data); echo '</pre>';
        fputcsv4($output, $data); 
    }
    fclose($output);
?>

So, we have a routine wherein a query is run, $output is established with fopen, added to via foreach statements, and finally fclosed.

The error that I’m getting (from the server) is

Error 6 (net::ERR_FILE_NOT_FOUND): The file or directory could not be found.

But it clearly is getting found, its just failing. If I enable phpinfo() (PHP Version 5.2.17) at the top of the file, I definitely get a response – notably Cannot modify header information (because phpinfo() has already generated a header). All the expected data does get printed to the page, however, so that much, at least is working correctly.

I am guessing there is something preventing the fopen, fclose functions from working properly, but I don’t have enough experience with this to identify exactly what the problem is.

I’ll note again that this works exactly as expected in my test environment (localhost/XAMPP, netbeans).

Any thoughts would be most appreciated.

Related posts

Leave a Reply

1 comment

  1. Try this:

    <?php
       header("Content-type: application/csv");
       header('Content-Disposition: inline; filename="export.csv"'); // change this filename
       include ('../../../wp-load.php'); // may need to change number of "../" depending upon location
       global $wpdb;
       $rows = $wpdb->get_results ("SELECT * FROM {$wpdb->prefix}table_name"); // change the table name
       echo strtolower(implode(',', array_keys((array)$rows[0]))) . "rn"; // fixes an Excel bug if the first column is "ID"
       foreach($rows as $row) echo '"' . implode ('","', array_values((array)$row)) . '"' . "rn";
    ?>
    

    This will automatically format the entire contents of the table as a CSV and stream the download straight to browser, raising a dialog prompting the user to save the file.