2013-06-27 40 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

相關問題