【问题标题】:how to serve output as file without saving it on server如何将输出作为文件提供而不将其保存在服务器上
【发布时间】:2012-08-13 18:23:52
【问题描述】:

我正在使用 PHP 的 fputcsv() 从 MySQL 数据库中提供一些记录,方法是在服务器上创建一个文件,填充它,然后在下一页链接到它。

这很好用,但由于这可能是敏感数据,我不希望在为(可能)一次性下载创建文件时在服务器上挂起一堆文件。

所以我想知道的是:有没有一种方法可以创建此文件并提供下载服务,而无需在服务器上实际写入永久文件?

例如,我可以创建一个逗号分隔的字符串,而不是使用fputcsv(),并在输出缓冲区中使用正确的标题来提供它吗?

显而易见的举动是删除文件,但我需要等到客户端先下载它,这样就很难决定何时删除。

欢迎提出建议

代码:

$fp = fopen($filename, 'w');
fputcsv($fp, array("Last Name", "First Name"));
foreach ($result as $fields) 
{
    fputcsv($fp, $fields);
}
fclose($fp);

http://php.net/manual/en/function.fputcsv.php

【问题讨论】:

    标签: php csv export-to-csv


    【解决方案1】:

    fputcsv() 是一个很棒的小函数,所以我不会放弃它。

    相反,我建议你使用 PHP 的内置 I/O Wrappers

    例如,您可以这样做以逐行“流式传输”您的 CSV 数据(取决于各种输出缓冲区,但这是另一回事):

    <?php
    header('Content-type: text/csv; charset=UTF-8');
    header('Content-disposition: attachment; filename=report.csv');
    $fp = fopen('php://output','w');
    foreach($arrays as $array) fputcsv($fp, $array);
    

    这很好用,但如果出现问题,您的用户将无法下载。

    所以,如果您没有太多数据,您可以只写入内存中的流,只需将 php://output 替换为 php://memory 并四处移动:

    <?php
    $fp = fopen('php://memory','rw');
    
    // our generateData() function might throw an exception, in which case 
    // we want to fail gracefully, not send the user a broken/incomplete csv.
    try {
        while($row = generateData()) fputcsv($fp, $row);
    }catch(\Exception $e){
        // display a nice page to your user and exit/return
    }
    
    // SUCCESS! - so now we have CSV data in memory.  Almost like we'd spooled it to a file
    //            on disk, but we didn't touch the disk.
    
    //rewind our file handle
    rewind($fp);
    
    //send output
    header('Content-type: text/csv; charset=UTF-8');
    header('Content-disposition: attachment; filename=report.csv');
    stream_get_contents($fp);
    

    【讨论】:

      【解决方案2】:

      与其相反,为什么不让您的页面回显csv mime type,然后将文件回显给用户?

      它很有魅力,文件永远不会被创建并作为一个文件传递给客户端。

      类似这样的:

      header("Content-type: application/csv");
      header("Content-Disposition: attachment; filename=file.csv");
      header("Pragma: no-cache");
      header("Expires: 0");
      
      echo "col1,col2";
      for($i=0; $i<25;$i++)
      {
          echo "key :".$i.", ".($i*$i)."\r\n";
      }
      

      您应该能够按原样对其进行测试,看看它是如何工作的。

      增加的好处是大多数用户将被引导下载文件而不是打开文件,因此用户甚至不会离开页面(大部分时间)。

      【讨论】:

      • 知道我过于复杂了。谢谢!顺便说一句,你在 for 中有第二个左括号:)
      • 不用担心。修复了括号(以及最初的其他拼写错误):)
      • 刚刚测试了这个,它完成了工作。再次感谢,mime 类型列表的链接也很方便:)
      猜你喜欢
      • 2021-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-25
      • 2012-12-08
      • 1970-01-01
      • 1970-01-01
      • 2012-12-04
      相关资源
      最近更新 更多