使用fwrite和fread与输入流的PHP

使用fwrite和fread与输入流的PHP,php,inputstream,Php,Inputstream,我正在寻找将PHP输入流的内容写入磁盘的最有效的方法,而不需要使用授予PHP脚本的大部分内存。例如,如果可以上载的最大文件大小为1GB,但PHP只有32MB的内存 define('MAX_FILE_LEN', 1073741824); // 1 GB in bytes $hSource = fopen('php://input', 'r'); $hDest = fopen(UPLOADS_DIR.'/'.$MyTempName.'.tmp', 'w'); fwrite($hDest, fread

我正在寻找将PHP输入流的内容写入磁盘的最有效的方法,而不需要使用授予PHP脚本的大部分内存。例如,如果可以上载的最大文件大小为1GB,但PHP只有32MB的内存

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提供了一个名为的函数,我相信它不会将文件内容保存在PHP脚本的内存中


我正在寻找类似的东西,但方向相反(从输入流写入文件)。感谢您提供的任何帮助。

是的-
fread
以这种方式使用时,会先将高达1 GB的数据读入字符串,然后通过
fwrite
将其写回。PHP不够聪明,无法为您创建一个内存高效的管道

我会尝试以下类似的方法:

$hSource=fopen('php://input","r",;
$hDest=fopen(上传_DIR.'/'.$MyTempName.'.tmp','w');
而(!feof($hSource)){
/*  
*我要读1K块,你可以做这个
*更大,但根据经验,我会把它保持在
*您的php内存不足。
*/
$chunk=fread($hSource,1024);
fwrite($hDest,$chunk);
}
fclose($hSource);
fclose($hDest);

如果你真的想挑剔,你也可以
unset($chunk)fwrite
之后的循环中进行code>以绝对确保PHP释放内存-但这不是必需的,因为下一个循环将覆盖
$chunk
当时正在使用的任何内存。

谢谢pauld,我也喜欢你使用unset的想法。@pauld Nice!为了获得最佳性能,unset应该像
while(…){…}unset($chunk)那样使用重新分配内存每次迭代不会有太大的影响,但释放内存之后,在这里有点重要。@ TonyChiboucas为什么要释放1024字节的内存?@ MijjnZ0R,因为这可能发生在更长的PHP线程的中间,在数千个并行请求中。撇开潜在的内存泄漏和loris速度变慢不谈,在生产环境中(例如,作为记录器的一部分),这可能很快就会变成MB的内存。关于性能和内存管理,最重要的一点是每个字节都很重要。它们加起来了。@marijnz0r,遵循良好的实践并不是过早的优化。任何像这样在内存上运行的代码都应该总是释放内存。过早优化将是分析此代码的性能和一些变体,选择在大型数据集上完成时间最短的实现。“释放内存”不是早期优化。