CSV文件生成错误

时间:2011-07-27 14:50:31

标签: php mysql wordpress csv

我正在为客户开发一个项目 - 一个wordpress插件,用于创建和维护组织成员的数据库。我会注意到这个插件在wordpress数据库中创建了一个新表(而不是将数据作为custom_post_type元数据处理)。我已对插件的大部分内容进行了大量修改,但我遇到了一个功能问题(我保持不变)。

此功能的一半执行csv导入和插入,效果很好。此序列的另一半是将此表的内容作为csv下载的功能。此部分在我的本地系统上运行正常,但在从服务器运行时失败。我已经倾倒了这个剧本的每一部分,一切似乎都有意义。坦率地说,我不知道为什么会失败。

包含逻辑的php文件只是链接到。文件:

<?php
    // initiate wordpress
    include('../../../wp-blog-header.php');

    // 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);
    // 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){
        // 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);
?>

因此,显然,运行查询的例程$outputfopen建立,然后每行格式化为逗号分隔和fwrite d,最后文件为fclose d它被推送到本地系统。

我收到的错误(来自服务器)是

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

但它显然已经被发现,它只是失败了。如果我在文件顶部启用phpinfo()(PHP版本5.2.17),我肯定会收到回复 - 特别是Cannot modify header information(我很确定,因为phpinfo()已经生成了头)。然而,所有预期的数据都会打印到页面底部(在所有phpinfo诊断之后),因此至少可以正常工作。

我猜有些东西阻止fopenfwritefclose功能正常工作(服务器设置?),但我没有足够的经验准确地确定问题所在。

我会再次注意到,这在我的测试环境中完全符合预期(localhost / XAMPP,netbeans)。

任何想法都会非常感激。

更新

好的 - 今天花了一些时间。我已经尝试了每个建议的修复程序,包括@ Rudu的writeCSVLine修正和@Fernando Costa的file_put_contents()建议。事实是,它们都在本地工作。只是echofopenfwritefclose例程无关紧要,效果很好。

似乎有问题的是在文件的开头包含wp-blog-header.php,然后是其他header()次调用。 (路径在服务器上肯定是正确的,顺便说一句。)

如果我注释掉include,我会下载一个csv文件,其中包含一些错误(因为$wpdb不存在。如果注释掉header,我将所有数据打印到页面上。

那么......任何想法可能会在这里发生什么? wordpress环境的一些明显冲突和文件的正确创建。

学习很多,但没有接近答案......想想我可能只需要避免wordpress的东西并做一个手动的SQL查询。

2 个答案:

答案 0 :(得分:1)

好的,所以我想知道为什么你采取这种方法。 php://output没有错,但它只是允许您以与printecho 相同的方式写入输出缓冲区 ...如果您是遇到麻烦,只需使用print或echo :)你在流上使用fwrite得到的任何优化都会因为你构建$csv变量然后一次性编写而丢失到输出流(不是特别需要优化)。所有这些都是我的解决方案(与您的原始设计保持一致)将是这样的:

function escapeCSVcell($val) {
    return str_replace('"','""',$val);
    //What about new lines in values?  Perhaps not relevant to your
    // data but they'll mess up your output ;)
}
function writeCSVLine($arr) {
    $first=true;
    foreach ($arr as $v) {
        if (!$first) {echo ",";}
        $first=false;
        echo "\"".escapeCSVcell($v)."\"";
    }
    echo "\n"; // May want to use \r\n depending on consuming script
}

现在使用writeCSVLine代替fputcsv4

答案 1 :(得分:1)

进入同样的问题。偶然发现这个线程执行相同的操作,但挂钩到'plugins_loaded'操作并导出CSV然后。 https://wordpress.stackexchange.com/questions/3480/how-can-i-force-a-file-download-in-the-wordpress-backend

提前导出CSV消除了在您到达之前已经修改标头的风险。