【问题标题】:How to create and download a csv file from php script?如何从 php 脚本创建和下载 csv 文件?
【发布时间】:2013-04-21 12:34:55
【问题描述】:

我是一名新手程序员,我搜索了很多关于我的问题,但找不到有用的解决方案或教程。

我的目标是我有一个 PHP 数组,并且数组元素显示在页面上的列表中。

我想添加一个选项,这样如果用户需要,他/她可以创建一个包含数组元素的 CSV 文件并下载它。

我不知道该怎么做。我也搜索了很多。但尚未找到任何有用的资源。

请提供一些教程或解决方案或建议,让我自己实现它。由于我是新手,请提供易于实施的解决方案。

我的数组看起来像:

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

)

【问题讨论】:

  • 用于 CSV 文件的 phpExcel 有点太多了..php.net/manual/en/function.fputcsv.php
  • 显示您的数组结构,我可以提供一些代码将元素转换为 csv
  • @half-fast 我已经在帖子中添加了数组结构
  • 如何在csv文件中添加列标题?
  • Export to CSV via PHP的可能重复

标签: php export-to-csv


【解决方案1】:

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

$f = fopen("tmp.csv", "w");
foreach ($array as $line) {
    fputcsv($f, $line);
}

要让浏览器提供“另存为”对话框,您必须发送这样的 HTTP 标头(在 rfc 中查看有关此标头的更多信息):

header('Content-Disposition: attachment; filename="filename.csv";');

把它们放在一起:

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

你可以这样使用它:

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

更新:
除了php://memory,您还可以使用php://output 作为文件描述符并取消搜索等:

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

【讨论】:

  • 为什么不在循环中直接echo生成的CSV行?
  • @AlexShesterov,主要原因是fputcsv() 没有返回生成的行,它需要一个文件描述符来写入。如果内存有限,您可以在每次迭代时倒带、写入、清除缓冲区。或者只使用真正的临时文件。
  • @complex857 如何为 csv 添加列标题?
  • @user2302780:您只需在数据前面加上一行列名。您可以使用数据数组中的键,例如 $data = array_merge(array(array_keys($data[0])), $data);
  • @JoseRojas 这是意料之中的,因为一旦你把东西放在网上(用 php 输出东西在概念上意味着)你就不能回头了。要使用php://output,请参阅第二个更新的代码示例。
【解决方案2】:

如果你的数组结构总是以这种精确的方式是多维的,那么我们可以像这样遍历元素:

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

这是一种方法……您可以手动操作,但这种方法更快、更容易理解和阅读。

然后您将管理您的标头,就像 complex857 正在执行的吐出文件一样。然后,如果您不再需要该文件,可以使用 unlink() 删除该文件,或者如果您愿意,可以将其保留在服务器上。

【讨论】:

    【解决方案3】:

    我没有足够的声誉来回复@complex857 解决方案。它很好用,但我必须添加;在 Content-Disposition 标头的末尾。没有它,浏览器会在文件名末尾添加两个破折号(例如,文件保存为“export.csv--”而不是“export.csv”)。可能它会尝试清理标题行末尾的 \r\n。

    正确的行应该是这样的:

    header('Content-Disposition: attachment;filename="'.$filename.'";');
    

    如果 CSV 中包含 UTF-8 字符,您必须通过更改 Content-Type 行将编码更改为 UTF-8:

    header('Content-Type: application/csv; charset=UTF-8');
    

    另外,我发现使用 rewind() 代替 fseek() 更优雅:

    rewind($f);
    

    感谢您的解决方案!

    【讨论】:

    • 我自己从未体验过文件名末尾的--,但是我已经更新了答案(为什么不直接提交编辑?)
    【解决方案4】:

    试试... csv 下载。

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

    【讨论】:

    • 如果字段值包含 会中断,这就是为什么我更喜欢 tsv (标签比 更稀有,我们可以替换它或其他东西)
    • 简单易行。谢谢
    • "exit():" - 谢谢!!在我想要的数据之后,我得到了页面的整个 HTML
    【解决方案5】:

    使用以下代码将 php 数组转换为 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);
    

    【讨论】:

      【解决方案6】:

      这是我在项目中使用的功能,它按预期工作。

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

      【讨论】:

      • 我很难在 wordpress send_headers 钩子中实现它,因为每次它将所有当前页面 html 添加到 csv 文件的末尾。这些答案让我大吃一惊,但我在没有缓冲操作的情况下使用它。
      • clean output buffer为我解决了在使用这些代码行之前在形成文件的开头和结尾是空行的问题。
      猜你喜欢
      • 2020-09-07
      • 2020-10-15
      • 2023-01-04
      • 1970-01-01
      • 2015-01-05
      • 2015-05-03
      • 1970-01-01
      • 2015-03-16
      • 2014-01-17
      相关资源
      最近更新 更多