2013-06-27 41 views
0

所以我希望能够通过一个简单的解决方案来读取数据库中的记录并将其保存到用户下载的文本文件中。我一直在做这个动作,并且在20,000条记录下,这个工作很棒。超过20,000条记录,我正在将太多数据加载到内存中,并且PHP遇到了一个致命错误。将1000条记录输出到文本文件

我的想法是只抓住一切。所以我抓住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()); 
+0

命中哪个致命错误?知道这将有助于。例如,如果它是超时限制;增加它。内存限制为 –

+0

。而且我知道我可以增加内存限制(它在VPS上),但我想要一个可以扩展一点的解决方案,因为它已经达到了25,000个限制,我可能想在某个时间点导出数百万个 –

+0

我猜测输出缓冲区在文件末尾刷新之前已经填满了最大值。尝试将输出文件写入服务器上的磁盘,然后使用'readfile'将其作为下载文件发送。 – 2013-06-27 02:37:15

回答

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

+0

对于任何发现此线程的人来说,这绝对是最好的建议。我最终重写脚本以块处理,并使用AJAX获取反馈,以便向用户显示进度条。 –

0

你应该改变你的str_replace函数为addslashes()。这可能会释放一些内存。

然后我建议你保存一个文件并使用php文件功能来做到这一点:fopen()file_put_contents()

我希望这可以帮助你!

0

其实,这可能是简单的修复。如果PHP内存不足,可能是因为在发送文件之前输出缓冲区已满。如果是这样,只需定期flush()

这将每行后冲洗:冲洗后

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

每一行可能被证明过于缓慢,在这种情况下,添加计数器和冲洗每百户后,或什么效果最好。

+0

这是一个非常好的想法,但没有成功。内存是空的,因为我正试图在处理之前将所有结果加载到变量中... –

+0

C'est la vie。也许我下次会有更好的运气! – 2013-06-27 07:54:13

相关问题