2012-03-07 95 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