2012-03-07 96 views
5

我正在尋找將PHP輸入流的內容寫入磁盤的最有效方式,而不使用許多授予PHP腳本的內存。例如,如果可以上傳的最大文件大小是1 GB,但PHP只有32 MB的內存。使用fwrite和fread與輸入流的PHP

define('MAX_FILE_LEN', 1073741824); // 1 GB in bytes 
$hSource = fopen('php://input', 'r'); 
$hDest = fopen(UPLOADS_DIR.'/'.$MyTempName.'.tmp', 'w'); 
fwrite($hDest, fread($hSource, MAX_FILE_LEN)); 
fclose($hDest); 
fclose($hSource); 

在上面的代碼中寫入fwrite的fread是否意味着整個文件將被加載到內存中?

做相反(寫入文件輸出流),PHP提供了一個稱爲fpassthru,我相信沒有抱在PHP腳本的內存中的文件的內容的功能。

我正在尋找類似的東西,但在反向(寫入輸入流到文件)。感謝您提供任何幫助。

回答

3

Yep - fread以這種方式使用時,會首先讀取1 GB的字符串,然後通過fwrite將其寫回。 PHP只是沒有足夠的智能來爲你創建一個高效的內存管道。

我會嘗試一些類似於如下:

$hSource = fopen('php://input', 'r'); 
$hDest = fopen(UPLOADS_DIR . '/' . $MyTempName . '.tmp', 'w'); 
while (!feof($hSource)) { 
    /* 
    * I'm going to read in 1K chunks. You could make this 
    * larger, but as a rule of thumb I'd keep it to 1/4 of 
    * your php memory_limit. 
    */ 
    $chunk = fread($hSource, 1024); 
    fwrite($hDest, $chunk); 
} 
fclose($hSource); 
fclose($hDest); 

如果你想成爲真正挑剔,你也可以unset($chunk);fwrite後的循環中,以絕對確保PHP可以釋放內存 - 但是,這不應該沒有必要,因爲下一個循環會覆蓋當時$chunk正在使用的任何內存。

+0

感謝pauld,我喜歡你的使用unset的想法。 – Lakey 2013-08-30 02:39:20

+1

@ pauld好的!爲了獲得最佳性能,unset應該更像'while(...){...} unset($ chunk);'在每次迭代中重新分配內存不會有太大的影響,但釋放內存_after_,在這裏更重要一點。 – 2014-09-24 18:56:05

+0

@TonyChiboucas爲什麼你會釋放1024字節的內存? – marijnz0r 2017-04-05 15:02:11