我使用PHP的fputcsv()
通过在服务器上创建文件,填充它,然后在下一页链接到它来从MySQL数据库提供一些记录。
这很有用,但是因为这可能是敏感数据,所以我不希望在为(可能)一次性下载创建它们时在服务器上挂起一大堆文件。
所以我想知道的是:有没有办法创建这个文件&服务它下载而不实际在服务器上写一个永久文件?
例如,我可以创建逗号分隔的字符串而不是使用fputcsv()
并在输出缓冲区中使用正确的标头提供吗?
显而易见的举措是删除文件,但我需要等到客户端首先下载文件,这样才能决定何时进行操作。
欢迎任何建议
代码:
$fp = fopen($filename, 'w');
fputcsv($fp, array("Last Name", "First Name"));
foreach ($result as $fields)
{
fputcsv($fp, $fields);
}
fclose($fp);
答案 0 :(得分:6)
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);
答案 1 :(得分:3)
而不是那样,为什么不让你的页面回显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";
}
你应该能够按原样进行测试,看看它是如何工作的。
增加的美感是大多数用户将被指示下载文件而不是打开它,因此用户甚至不会离开页面(大部分时间)。