问得好。简短的回答是,PHP 必须处理整个 HTTP 请求 - 根据需要填写数据 - 然后再将控制权交给脚本。由于您的脚本在处理之后才获得控制权,因此无法告诉PHP将该文件数据放在何处。$_POST
$_FILES
但是为什么PHP会这样做呢?好吧,让我们看一下包含文件数据的HTTP POST:
POST /upload?upload_progress_id=12344 HTTP/1.1
Host: localhost:3000
Content-Length: 1325
Origin: http://localhost:3000
... other headers ...
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryePkpFF7tjBAqx29L
------WebKitFormBoundaryePkpFF7tjBAqx29L
Content-Disposition: form-data; name="MAX_FILE_SIZE"
100000
------WebKitFormBoundaryePkpFF7tjBAqx29L
Content-Disposition: form-data; name="uploadedfile"; filename="hello.o"
Content-Type: application/x-object
... contents of file goes here ...
------WebKitFormBoundaryePkpFF7tjBAqx29L--
请注意,请求的内容是多部分编码的文档,表单域穿插在文件数据中。在此特定示例中,表单字段出现在文件数据之前。但是,表单数据有可能 - 确实有可能 - 出现在文件数据之后。
所以,为了保证PHP能给你所有的数据,PHP必须处理整个请求。因此,当它在那里时,它也可以完成超级全球。$_POST
$_FILES
现在,PHP可以将此文件数据保存在内存中,但这可能真的是一个坏主意。想想如果PHP需要存储用户上传的100 MiB文件会发生什么。突然之间,你的Apache进程的RSS增加了100 MiB,这真的不是太好 - Apache可能会被占用那么多空间,或者Apache可能会被交换:让你的用户痛苦。因此,PHP做了下一个最好的事情:把这个收到的文件放在一个临时文件中。ulimit
您可能会问为什么不能告诉PHP首先放置传入文件数据的文件,因此您不必移动它。好吧,这是一个引导问题:PHP还没有将控制权移交给脚本,所以脚本无法告诉PHP在哪里放置文件。因此,PHP尽其所能:将文件数据放入临时文件中。
现在,您可以将此文件数据保存在RAM磁盘中,以便在需要时加快速度。如果您不介意基础架构成本(例如,维护RAM磁盘设置),这是一个好方法。但请注意,这不像PHP将其保存在RAM本身中:在这种情况下,PHP容器进程(通常是Apache或其他Web服务器)必须具有堆来保存文件(它可能不是)。在这种情况下,RAM 磁盘由内核管理。