【问题标题】:Create a CSV File for a user in PHP在 PHP 中为用户创建一个 CSV 文件
【发布时间】:2010-09-18 01:27:50
【问题描述】:

我在 MySQL 数据库中有数据。我正在向用户发送一个 URL,以将他们的数据作为 CSV 文件导出。

我已经涵盖了链接、MySQL 查询等的电子邮件。

当他们点击链接时,我怎样才能弹出一个窗口来下载带有 MySQL 记录的 CVS?

我已经掌握了获取记录的所有信息。我只是不明白如何让 PHP 创建 CSV 文件并让他们下载扩展名为 .csv 的文件。

【问题讨论】:

    标签: php csv download http-headers


    【解决方案1】:

    要让它以 CSV 格式发送并给出文件名,请使用 header():

    http://us2.php.net/header

    header('Content-type: text/csv');
    header('Content-disposition: attachment; filename="myfile.csv"');
    

    就制作 CSV 本身而言,您只需遍历结果集、格式化输出并发送它,就像您处理任何其他内容一样。

    【讨论】:

      【解决方案2】:

      试试:

      header("Content-type: text/csv");
      header("Content-Disposition: attachment; filename=file.csv");
      header("Pragma: no-cache");
      header("Expires: 0");
      
      echo "record1,record2,record3\n";
      die;
      

      编辑:这是我用来选择性地对 CSV 字段进行编码的 sn-p 代码:

      function maybeEncodeCSVField($string) {
          if(strpos($string, ',') !== false || strpos($string, '"') !== false || strpos($string, "\n") !== false) {
              $string = '"' . str_replace('"', '""', $string) . '"';
          }
          return $string;
      }
      

      【讨论】:

      • 注意 CSV 的规则很重要。为确保良好的显示效果,请在字段周围加上双引号,并且不要忘记将字段内的双引号替换为双双引号:`echo '"'.str_replace('"','""',$record1)。 '","'.str_replace....
      • 澄清一下,CSV 的正确 HTTP Content-Type 标头是 text/csv,而不是 application/csv。我怀疑任何现代浏览器都会关心这两种方式,但既然有标准,我们不妨使用它们。
      • 一般情况下,生成 CSV 文件时请遵循 RFC 4180。 tools.ietf.org/html/rfc4180
      • @Oleg Barshay:天哪,RFC 是一个杰作:“如果使用双引号括住字段,那么出现在字段中的双引号必须通过在它前面加上另一个双引号来转义引用。”。另一个双引号!
      【解决方案3】:

      创建您的文件,然后使用正确的标题返回对它的引用以触发另存为 - 根据需要编辑以下内容。将您的 CSV 数据放入 $csvdata。

      $fname = 'myCSV.csv';
      $fp = fopen($fname,'wb');
      fwrite($fp,$csvdata);
      fclose($fp);
      
      header('Content-type: application/csv');
      header("Content-Disposition: inline; filename=".$fname);
      readfile($fname);
      

      【讨论】:

      • 使用“inline”Content-Disposition 意味着浏览器应该尝试在不下载的情况下显示它(IE 倾向于为此嵌入一个 Excel 实例)。 “附件”是强制下载所需要的。
      【解决方案4】:
      <?
          // Connect to database
          $result = mysql_query("select id
          from tablename
          where shid=3");
          list($DBshid) = mysql_fetch_row($result);
      
          /***********************************
          Write date to CSV file
          ***********************************/
      
          $_file = 'show.csv';
          $_fp = @fopen( $_file, 'wb' );
      
          $result = mysql_query("select name,compname,job_title,email_add,phone,url from UserTables where id=3");
      
          while (list( $Username, $Useremail_add, $Userphone, $Userurl) = mysql_fetch_row($result))
          {
              $_csv_data = $Username.','.$Useremail_add.','.$Userphone.','.$Userurl . "\n";
              @fwrite( $_fp, $_csv_data);
          }
          @fclose( $_fp );
      ?>
      

      【讨论】:

        【解决方案5】:

        首先将数据制作为以逗号为分隔符的字符串(用“,”分隔)。像这样的

        $CSV_string="No,Date,Email,Sender Name,Sender Email \n"; //making string, So "\n" is used for newLine
        
        $rand = rand(1,50); //Make a random int number between 1 to 50.
        $file ="export/export".$rand.".csv"; //For avoiding cache in the client and on the server 
                                             //side it is recommended that the file name be different.
        
        file_put_contents($file,$CSV_string);
        
        /* Or try this code if $CSV_string is an array
            fh =fopen($file, 'w');
            fputcsv($fh , $CSV_string , ","  , "\n" ); // "," is delimiter // "\n" is new line.
            fclose($fh);
        */
        

        【讨论】:

          【解决方案6】:

          简单的方法——

          $data = array (
              'aaa,bbb,ccc,dddd',
              '123,456,789',
              '"aaa","bbb"');
          
          $fp = fopen('data.csv', 'wb');
          foreach($data as $line){
              $val = explode(",",$line);
              fputcsv($fp, $val);
          }
          fclose($fp);
          

          所以$data 数组的每一行都将转到新创建的 CSV 文件的新行。它仅适用于 PHP 5 及更高版本。

          【讨论】:

            【解决方案7】:

            代替:

            $query = "SELECT * FROM customers WHERE created>='{$start} 00:00:00'  AND created<='{$end} 23:59:59'   ORDER BY id";
            $select_c = mysql_query($query) or die(mysql_error()); 
            
            while ($row = mysql_fetch_array($select_c, MYSQL_ASSOC))
            {
                $result.="{$row['email']},";
                $result.="\n";
                echo $result;
            }
            

            用途:

            $query = "SELECT * FROM customers WHERE created>='{$start} 00:00:00'  AND created<='{$end} 23:59:59'   ORDER BY id";
            $select_c = mysql_query($query) or die(mysql_error()); 
            
            while ($row = mysql_fetch_array($select_c, MYSQL_ASSOC))
            {
                echo implode(",", $row)."\n";
            }
            

            【讨论】:

              【解决方案8】:

              将 CSV 数据放入 $output 变量中,并使用正确的标题回显

              header("Content-type: application/download\r\n");
              header("Content-disposition: filename=filename.csv\r\n\r\n");
              header("Content-Transfer-Encoding: ASCII\r\n");
              header("Content-length: ".strlen($output)."\r\n");
              echo $output;
              

              【讨论】:

                【解决方案9】:
                header("Content-Type: text/csv");
                header("Content-Disposition: attachment; filename=file.csv");
                
                function outputCSV($data) {
                  $output = fopen("php://output", "wb");
                  foreach ($data as $row)
                    fputcsv($output, $row); // here you can change delimiter/enclosure
                  fclose($output);
                }
                
                outputCSV(array(
                  array("name 1", "age 1", "city 1"),
                  array("name 2", "age 2", "city 2"),
                  array("name 3", "age 3", "city 3")
                ));
                

                php://output
                fputcsv

                【讨论】:

                • 更多人需要看到这个并投票。这很容易成为此页面上的最佳答案。 PHP 已经具有用于格式化 CSV 内容的内置函数。每个人都应该使用它们。很好的答案,@Andrey :)
                • 太糟糕了 fputcsv() 不能正常工作:( bugs.php.net/bug.php?id=50686
                • 很好,但是outputCSV 函数是不必要的复杂。您可以通过$array 直接将其值发送到foreach,将其值直接发送到fputcsv。不需要__outputCSVarray_walk :) foreach($data as $vals) {fputcsv($filehandler,$vals);}
                • 数组中的法语字符存在一些问题,因为我最终需要在 Excel 中打开 .csv。它在重音字符上窒息。 "Prévalence","age 1","city 1" 之类的东西有什么想法吗?到目前为止,混用 UTF-8 并没有帮助。
                • @theosem 分隔符取决于操作系统或 Excel 导出设置。我添加了关于分隔符的注释。
                【解决方案10】:

                最简单的方法是像这样使用专用的CSV class

                $csv = new csv();
                $csv->load_data(array(
                    array('name'=>'John', 'age'=>35),
                    array('name'=>'Adrian', 'age'=>23), 
                    array('name'=>'William', 'age'=>57) 
                ));
                $csv->send_file('age.csv'); 
                

                【讨论】:

                  【解决方案11】:

                  这个帖子有点老了,我知道,但供将来参考和像我一样的菜鸟:

                  这里的其他人都解释了如何创建 CSV,但忽略了问题的一个基本部分:如何链接。为了链接到 CSV 文件的下载,您只需链接到 .php 文件,该文件又以 .csv 文件的形式响应。 PHP 标头就是这样做的。这可以实现一些很酷的东西,比如向查询字符串添加变量并自定义输出:

                  <a href="my_csv_creator.php?user=23&amp;othervariable=true">Get CSV</a>
                  

                  my_csv_creator.php 可以使用查询字符串中给出的变量,例如使用不同的或自定义的数据库查询、更改 CSV 的列、个性化文件名等等,例如:

                  User_John_Doe_10_Dec_11.csv
                  

                  【讨论】:

                  • 呃 - 任何阅读本文的人都非常警惕这种方法。我敢打赌,输入没有被正确转义,这可能会导致您的应用程序出现重大安全漏洞。
                  • 他的方法很安全,效果很好。您可以通过会话轻松控制访问,还可以将要放入 csv 中的所有信息存储在会话 var 中。然后将其取消设置为将其转换为 csv 的过程的一部分。我只是建议使用会话变量而不是查询字符串。
                  • 这种方法本身没有安全漏洞。只要引用的 php 文件正在执行它的卫生和访问检查工作。但是在这里展示所有这些并没有什么意义。这篇文章的重点是您可以链接到生成 csv 的任何 url。
                  【解决方案12】:

                  这是@Andrew 发布的 php.net 函数的改进版本。

                  function download_csv_results($results, $name = NULL)
                  {
                      if( ! $name)
                      {
                          $name = md5(uniqid() . microtime(TRUE) . mt_rand()). '.csv';
                      }
                  
                      header('Content-Type: text/csv');
                      header('Content-Disposition: attachment; filename='. $name);
                      header('Pragma: no-cache');
                      header("Expires: 0");
                  
                      $outstream = fopen("php://output", "wb");
                  
                      foreach($results as $result)
                      {
                          fputcsv($outstream, $result);
                      }
                  
                      fclose($outstream);
                  }
                  

                  它非常易于使用,并且非常适合 MySQL(i)/PDO 结果集。

                  download_csv_results($results, 'your_name_here.csv');
                  

                  如果您已完成页面,请记住在调用此代码后exit()

                  【讨论】:

                  • 如何将分隔符从 , 更改为 ; ?
                  • 我们应该如何添加一个按钮来触发这个事件,以便用户能够按需下载 CSV 文件?
                  • 我将在 "fopen("php://output", "w");" 行出现 "SyntaxError: Unexpected token ILLEGAL" 错误当我将其更改为“$fp = fopen('stats.csv', 'w');”时它不显示错误。但是当然它不起作用。我该如何解决?
                  • @CanCeylan,这本身就是一个问题,我需要更多细节来解决它。
                  • 在您的 foreach 之前添加 fputcsv($outstream, array_keys($results[0])); 以包括列标题。
                  【解决方案13】:

                  如何使用 PHP 脚本写入 CSV 文件?其实我也在找那个。使用 PHP 是一件容易的事。 fputs(handler, content) - 这个函数对我来说很有效。首先,您需要使用 fopen($CSVFileName, ‘wb’) 打开需要写入内容的文件。

                  $CSVFileName = “test.csv”;
                  $fp = fopen($CSVFileName, ‘wb’);
                  
                  //Multiple iterations to append the data using function fputs()
                  foreach ($csv_post as $temp)
                  {
                      $line = “”;
                      $line .= “Content 1″ . $comma . “$temp” . $comma . “Content 2″ . $comma . “16/10/2012″.$comma;
                      $line .= “\n”;
                      fputs($fp, $line);
                  }
                  

                  【讨论】:

                  • 总是倾向于将代码添加到 so 本身而不是链接,因为链接会随着时间的推移而改变或消失。
                  • 您的答案是一个非常古老的线程。虽然在 2008 年,建立自己的逗号分隔行是标准做法,但自 PHP 5.1.0 以来的正确方法是使用内置的 fputcsv 函数 (php.net/fputcsv)。阅读旧线程时要小心,以确保其中包含的信息仍然相关。
                  【解决方案14】:

                  已经非常好的解决方案来了。我只是把总代码,以便新手得到全面的帮助

                  <?php
                  extract($_GET); //you can send some parameter by query variable. I have sent table name in *table* variable
                  
                  header("Content-type: text/csv");
                  header("Content-Disposition: attachment; filename=$table.csv");
                  header("Pragma: no-cache");
                  header("Expires: 0");
                  
                  require_once("includes/functions.php"); //necessary mysql connection functions here
                  
                  //first of all I'll get the column name to put title of csv file.
                  $query = "SHOW columns FROM $table";
                  $headers = mysql_query($query) or die(mysql_error());
                  $csv_head = array();
                  while ($row = mysql_fetch_array($headers, MYSQL_ASSOC))
                  {
                      $csv_head[] =  $row['Field'];
                  }
                  echo implode(",", $csv_head)."\n";
                  
                  //now I'll bring the data.
                  $query = "SELECT * FROM $table";
                  $select_c = mysql_query($query) or die(mysql_error()); 
                  
                  while ($row = mysql_fetch_array($select_c, MYSQL_ASSOC))
                  {
                      foreach ($row as $key => $value) {
                              //there may be separator (here I have used comma) inside data. So need to put double quote around such data.
                          if(strpos($value, ',') !== false || strpos($value, '"') !== false || strpos($value, "\n") !== false) {
                              $row[$key] = '"' . str_replace('"', '""', $value) . '"';
                          }
                      }
                      echo implode(",", $row)."\n";
                  }
                  
                  ?>
                  

                  我已将此代码保存在 csv-download.php 中

                  现在看看我是如何使用这些数据下载 csv 文件的

                  <a href="csv-download.php?table=tbl_vfm"><img title="Download as Excel" src="images/Excel-logo.gif" alt="Download as Excel" /><a/>
                  

                  因此,当我单击该链接时,它会下载文件而不会将我带到浏览器上的 csv-download.php 页面。

                  【讨论】:

                    【解决方案15】:

                    嘿,效果很好....!!!!感谢 Peter Mortensen 和 Connor Burton

                    <?php
                    header("Content-type: application/csv");
                    header("Content-Disposition: attachment; filename=file.csv");
                    header("Pragma: no-cache");
                    header("Expires: 0");
                    
                    ini_set('display_errors',1);
                    $private=1;
                    error_reporting(E_ALL ^ E_NOTICE);
                    
                    mysql_connect("localhost", "user", "pass") or die(mysql_error());
                    mysql_select_db("db") or die(mysql_error());
                    
                    $start = $_GET["start"];
                    $end = $_GET["end"];
                    
                    $query = "SELECT * FROM customers WHERE created>='{$start} 00:00:00'  AND created<='{$end} 23:59:59'   ORDER BY id";
                    $select_c = mysql_query($query) or die(mysql_error());
                    
                    while ($row = mysql_fetch_array($select_c, MYSQL_ASSOC))
                    {
                        $result.="{$row['email']},";
                        $result.="\n";
                        echo $result;
                    }
                    

                    ?>

                    【讨论】:

                    • 不要在生产中使用此代码,它容易受到 SQL 注入的攻击
                    【解决方案16】:

                    除了已经说过的,你可能还需要补充:

                    header("Content-Transfer-Encoding: UTF-8");
                    

                    在处理包含多种语言的文件时非常有用,例如人名或城市。

                    【讨论】:

                      【解决方案17】:

                      这是一个使用 PDO 并包含列标题的完整工作示例:

                      $query = $pdo->prepare('SELECT * FROM test WHERE id=?');
                      $query->execute(array($id));    
                      $results = $query->fetchAll(PDO::FETCH_ASSOC);
                      download_csv_results($results, 'test.csv'); 
                      exit();
                      
                      
                      function download_csv_results($results, $name)
                      {            
                          header('Content-Type: text/csv');
                          header('Content-Disposition: attachment; filename='. $name);
                          header('Pragma: no-cache');
                          header("Expires: 0");
                      
                          $outstream = fopen("php://output", "wb");    
                          fputcsv($outstream, array_keys($results[0]));
                      
                          foreach($results as $result)
                          {
                              fputcsv($outstream, $result);
                          }
                      
                          fclose($outstream);
                      }
                      

                      【讨论】:

                        【解决方案18】:

                        您可以使用fputcsv 函数简单地将数据写入CSV。让我们看看下面的例子。将列表数组写入 CSV 文件

                        $list[] = array("Cars", "Planes", "Ships");
                        $list[] = array("Car's2", "Planes2", "Ships2");
                        //define headers for CSV 
                        header('Content-Type: text/csv; charset=utf-8');
                        header('Content-Disposition: attachment; filename=file_name.csv');
                        //write data into CSV
                        $fp = fopen('php://output', 'wb');
                        //convert data to UTF-8 
                        fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF));
                        foreach ($list as $line) {
                            fputcsv($fp, $line);
                        }
                        fclose($fp);
                        

                        【讨论】:

                          【解决方案19】:

                          编写您自己的 CSV 代码可能是在浪费您的时间,只需使用一个包,例如 League/csv - 它为您处理所有困难的事情,文档很好,并且非常稳定/可靠:

                          http://csv.thephpleague.com/

                          您需要使用作曲家。如果你不知道作曲家是什么,我强烈推荐你看看:https://getcomposer.org/

                          【讨论】:

                            猜你喜欢
                            • 2014-06-09
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2013-06-02
                            • 1970-01-01
                            • 1970-01-01
                            • 2013-03-08
                            • 1970-01-01
                            相关资源
                            最近更新 更多