0

所以我希望能够通过一个简单的解决方案来从数据库中读取记录并将它们保存到用户下载的文本文件中。我一直在动态执行此操作,并且记录了不到 20,000 条记录,效果很好。超过 20,000 条记录,我将太多数据加载到内存中,PHP 遇到了致命错误。

我的想法是把所有东西都分成几块。所以我抓取 XX 行并将它们回显到文件中,然后循环获取下 XX 行,直到完成。

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

简而言之,此时的问题是,在多达 20,000 行的情况下,文件可以完美地构建和下载。不仅如此,我得到一个空文件。

编码:

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());
4

3 回答 3

1

非常大的桌子不会那样工作。

您必须在从数据库中读取数据时输出数据。如果您需要排序,请为此目的使用数据库 ORDER BY。

所以或多或少

// 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 中定义。如果您预计表格会增长很多,您可以将其设置为零。

于 2013-06-27T02:38:34.127 回答
0

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

然后我建议你保存一个文件并使用 php 文件函数来这样做:fopen()file_put_contents().

我希望这对你有帮助!

于 2013-06-27T02:38:23.770 回答
0

实际上,这可能是简单的解决方法。如果 PHP 内存不足,可能是因为在发送文件之前输出缓冲区已满。如果是这样,只需flush()定期进行。

这将在每一行之后刷新:

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

在每行之后刷新可能会太慢,在这种情况下,添加一个计数器并在每 100 个之后刷新,或者任何最有效的方法。

于 2013-06-27T02:47:56.440 回答