尝试下载从我的数据库创建的CSV文件时出错

时间:2017-02-28 11:46:51

标签: php csv

我正在尝试使用内置的PHP函数fputcsv()从我的数据库下载一个简单的CSV文件。

这是我的功能:

/**
 * downloads class logs in csv format
 */
public function ajaxDownloadTeachersClassLogs()
{
    // ...code to get data from the database...
    $classes = $query->result();

    // download file
    header("Content-Type: text/csv");
    header("Content-Disposition: attachment; filename=file.csv");

    // write data to file
    $output = fopen("php://output", "w");
    foreach ($classes as $class) {
        fputcsv($output, $class);
    }
    // change delimiter/enclosure
    fclose($output);
}

我知道我的数据库查询是正确的,因为当我var_dump($classes);时,我得到以下结果:

array(1) {
  [0]=>
  object(stdClass)#26 (10) {
    ["token"]=>
    string(5) "9DFCF"
    ["teacher_name"]=>
    string(17) "James Dean" 
    ["teacher_id"]=>
    string(1) "2"
    ["student_name"]=>
    string(11) "Juan Santos"
    ["student_id"]=>
    string(2) "26"
    ["class_number"]=>
    string(3) "1/1"
    ["started"]=>
    string(10) "1488279490"
    ["duration"]=>
    string(4) "1200"
    ["invite_email"]=>
    string(0) ""
    ["status"]=>
    string(0) ""
  }
}

当我运行该函数时,我收到以下错误:

enter image description here

如果我点击“确定”,则下载失败。

为什么我的下载失败?

修改

看起来我的问题与我使用的框架中的错误配置导致的内容编码错误有关...

以下代码有效:

$this->db->order_by('started');
$query = $this->db->get('classes');

header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename=data.csv;');

$flag = false;
$output = fopen('php://output', 'w');
foreach ($query->result_array() as $row) {
    if ($flag === false) {
        fputcsv($output, array_keys($row), ',');
    }
    fputcsv($output, array_values($row), ',');
}
die;

2 个答案:

答案 0 :(得分:1)

尝试以下步骤:

  • 首先制作带有硬代码数据的CSV,以检查是否出现同样的问题。
  • 如果硬编码数据仍然出现问题,那么:

    select t.code, v.colname, concat(t.code, '-', v.colname), v.val from t cross apply (values ([047], 'O47'), ([068], '068'), . . . ) v(val, colname);

而不是在一些项目$output = fopen("php://output", "w");中写入文件,看看会发生什么。

答案 1 :(得分:1)

您可以使用内置的fputcsv()为您的数组生成正确的csv行,因此您必须循环并收集这些行。像:

   // 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 ($classes as $class) {
        fputcsv($output, $class);
    }
    // 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: application/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);