为什么PHP将上传的文件存储在临时位置,有什么好处?

2022-08-30 08:54:25

好吧,我在这个领域是全新的,并浏览了一些教程,我发现在PHP中上传文件时,它会将它们存储在临时位置。

$file_temp=$_FILES['file']['tmp_name'];
$file_loc="Upload".$file_name;
move_uploaded_files($file_temp,$file_loc);

那么,为什么 PHP 不允许将文件直接上传到所需位置?为什么它们存储在具有.tmp扩展的临时位置,我们从此策略中获得什么好处?


答案 1

问得好。简短的回答是,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 磁盘由内核管理。


答案 2

写入临时位置,然后将其复制到预期目标有什么好处?

  • 在大多数平台上,文件移动是原子的,但文件写入不是(特别是如果您无法一次性写入所有数据)。因此,如果您有典型的生产者/消费者模式(一个进程生成文件,另一个进程监视目录并拾取找到的所有内容),则首先写入临时文件夹,然后才移动到实际位置意味着消费者永远看不到未完成的文件。
  • 如果写入文件的过程在中途死亡,则磁盘上有一个损坏的文件。如果它在真实位置,您必须自己清理它,但如果它位于临时位置,操作系统将负责。如果文件恰好是在备份作业运行时创建的,则该作业可能会选取不完整的文件。临时目录通常从备份中排除,因此只有在移动到最终目标后才会包含该文件。
  • 临时目录可能位于快速但易失性的文件系统(例如虚拟硬盘)上,这对于并行下载同一文件的多个块或对具有大量搜索的文件进行就地处理之类的事情可能是有益的。此外,与读取、写入和删除频率较低的目录相比,临时目录往往会导致更多的碎片,并且将临时目录保留在单独的分区上有助于保持其他分区的碎片减少。

推荐