PHP-零长度(空)CSV,但仅适用于较大的数据集
虽然我的应用程序是使用Yii框架构建的,但这更多的是一个普通的PHP问题(我认为) 我有一些代码,它接受一个Yii,在它上面循环并构建一个CSV导出。这非常有效,可以正确地构建和发送CSV 我在尝试导出较大的数据集时遇到问题。我已经成功地输出了约2500条记录,没有任何问题,但当我为一组更大的数据(约5000条记录)运行完全相同的代码时,脚本似乎运行正常,但发送一个零长度/空白CSV。我不明白为什么。。。它似乎运行了一段时间,然后发送CSV,日志中没有错误或警告。可能是输出在准备就绪之前正在刷新或类似吗 代码如下(为了清晰起见,这里添加了几个内联注释):PHP-零长度(空)CSV,但仅适用于较大的数据集,php,csv,yii,export,Php,Csv,Yii,Export,虽然我的应用程序是使用Yii框架构建的,但这更多的是一个普通的PHP问题(我认为) 我有一些代码,它接受一个Yii,在它上面循环并构建一个CSV导出。这非常有效,可以正确地构建和发送CSV 我在尝试导出较大的数据集时遇到问题。我已经成功地输出了约2500条记录,没有任何问题,但当我为一组更大的数据(约5000条记录)运行完全相同的代码时,脚本似乎运行正常,但发送一个零长度/空白CSV。我不明白为什么。。。它似乎运行了一段时间,然后发送CSV,日志中没有错误或警告。可能是输出在准备就绪之前正在刷新
非常感谢您提供检查错误日志的建议,我不知何故错过了一个内存不足的错误
这个问题实际上是由我使用Yii框架中的方法引起的。正如我在问题中所做的那样,直接从数据提供者读取数据就是将每一行读取到内存中,因为脚本在此基础上运行意味着我最终耗尽了PHP可用的内存
有两种方法可以解决这个问题,一种是将数据提供程序上的分页设置为较小数量的记录,并手动迭代数据,每次迭代仅将页面大小加载到内存中
我选择的方法是使用a为我处理这个问题$iterator=new CDATA提供的迭代器($dp)代码>这可以防止内存被我正在检索的记录填满
注意,我还必须添加一个ob_flush()代码>调用以防止输出缓冲区填满CSV内容iteslf
作为参考,我最后得出以下结论:
<?php
header('Content-type: text/csv');
header('Content-Disposition: attachment; filename="vacancies.csv"');
set_time_limit(240);
$outstream = fopen("php://output", 'w');
$headings = array(
$vacancy->getAttributeLabel('vacancy_id'),
...
);
fputcsv($outstream, $headings, ',', '"');
$iterator = new CDataProviderIterator($dp); // create an iterator instead of just using the dataprovider
foreach($iterator as $vacancy){ // use the new iterator here
$row = array(
$vacancy->vacancy_id,
...
);
fputcsv($outstream, $row, ',', '"');
ob_flush(); // explicitly call a flush to avoid filling the buffer
}
fclose($outstream);
?>
超时?内存超出?检查服务器日志您是否尝试过整理输出,然后传输标题(包括内容长度
标题)和数据?感谢您的回复,我已经检查了apache错误日志,写文件时确实看起来内存不足。出于某种原因,我没有早点发现这一点。将该文件写入磁盘可以使我在它死之前获得大约3000条记录。现在我需要弄清楚如何在不耗尽内存的情况下编写文件!顺便说一句,接受你自己的答案绝对没有错,特别是当它提供了这样一个很好的细节水平时。谢谢,我直到现在才能够接受它,因为我的帐户是相当新的。现在已经这样做了:)
<?php
header('Content-type: text/csv');
header('Content-Disposition: attachment; filename="vacancies.csv"');
set_time_limit(240);
$outstream = fopen("php://output", 'w');
$headings = array(
$vacancy->getAttributeLabel('vacancy_id'),
...
);
fputcsv($outstream, $headings, ',', '"');
$iterator = new CDataProviderIterator($dp); // create an iterator instead of just using the dataprovider
foreach($iterator as $vacancy){ // use the new iterator here
$row = array(
$vacancy->vacancy_id,
...
);
fputcsv($outstream, $row, ',', '"');
ob_flush(); // explicitly call a flush to avoid filling the buffer
}
fclose($outstream);
?>