将1000条记录输出到文本文件


Output 1,000s of records to text file

所以我希望能够通过一个简单的解决方案从数据库中读取记录并将其保存到用户下载的文本文件中。我一直在做这件事,在不到20000张唱片的记录中,这件事做得很好。超过20000条记录,我将太多数据加载到内存中,PHP遇到了一个致命错误。

我的想法是把所有东西都大块地抓起来。因此,我获取XX行数并将其回显到文件中,然后循环获取下一个XX行,直到完成为止。

不过,我现在只是在回应结果,而不是构建文件然后发送下载,我想我必须这样做

简洁地说,此时的问题是,该文件最多有20000行,可以完美地构建和下载。除此之外,我得到了一个空文件。

代码:

header('Content-type: application/txt');
header('Content-Disposition: attachment; filename="export.'.$file_type.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
// I do other things to check for records before, hence the do-while loop
$this->items = $model->getItems();
do {
    foreach ($this->items as $k => $item) {
        $i=0;
        $tables = count($this->data['column']);
        foreach ($this->data['column'] as $table => $fields) {
            $columns = count($fields);
            $j = 0;
            foreach ($fields as $field => $junk) {
                if ($quote_output) {
                    echo '"'.ucwords(str_replace(array('"'), array(''"'), $item->$field)).'"';
                } else {
                    echo ''.$item->$field.'';
                }
                $j++;
                if ($j<$columns) {
                    echo $delim;
                }
            }
            $i++;
            if ($i<$tables) {
                echo $delim;
            }
        }
        echo "'n";
    }
} while($this->items = $this->_model->getItems());

非常大的表不能以这种方式工作。

您必须在从数据库中读取数据时输出数据。如果您需要排序,那么可以使用数据库ORDERBY进行排序。

所以或多或少的

// assuming you use a var such as $query to handle the DB
while(!$query->eof())
{
  $fields = $query->read_next();
  echo $fields; // with your formatting, maybe call a function...
}

空结果是正常的。如果在发生任何回显之前内存已耗尽,则不会向浏览器发送任何内容。

还要注意,PHP有一个时间限制(看门狗),您可能需要对其进行调整。默认值是在php.ini中定义的。如果您希望表增长很大,可以将其设置为零。

您应该更改addslashes()的str_replace。这可能会释放一些内存。

然后我建议您保存一个文件,并使用php文件函数:fopen()file_put_contents()

我希望这能对你有所帮助!

实际上,这可能是一个简单的修复方法。如果PHP内存不足,可能是因为在发送文件之前,输出缓冲区已满。如果是这样的话,只需每隔一段时间flush()即可。

这将在每条线路后冲洗:

do {
    foreach(...) {
       // assemble your output line here
    }
      echo "'n";
      flush();
    }
} while($this->items = $this->_model->getItems());

每行之后的冲洗可能会被证明太慢,在这种情况下,添加一个计数器,每一百行之后冲洗一次,或者任何最有效的方法。