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

Jai*_*esh 65 php file-upload

好吧,我在这个领域是全新的,并通过一些教程,我发现在PHP上传文件时,它将它们存储在一个临时位置.

$file_temp=$_FILES['file']['tmp_name'];
$file_loc="Upload".$file_name;
move_uploaded_files($file_temp,$file_loc);
Run Code Online (Sandbox Code Playgroud)

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

bis*_*hop 79

好问题.简短的回答是,在控制脚本之前,PHP必须处理整个 HTTP请求 - 填写$_POST数据并$_FILES根据需要填写.由于您的脚本在处理之后才获得控制权,因此无法告诉PHP将文件数据放在何处.

但是为什么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--
Run Code Online (Sandbox Code Playgroud)

请注意,请求的内容是多部分编码文档,表单字段散布在文件数据中.在此特定示例中,表单字段出现文件数据之前.但是,可能 - 实际上可能 - 表单数据发生文件数据之后.

因此,为了确保 PHP可以给你所有$_POST数据,PHP必须处理整个请求.因此,它可以完成$_FILES超级全局,而它就在那里.

现在,PHP 可以将这些文件数据保存在内存中,但这可能是一个坏主意.想想如果PHP需要存储用户上传的100 MiB文件会发生什么.突然间,你的Apache进程的RSS增加了100 MiB,实际上并不太好 - Apache可能ulimit没有那么大的空间,或者Apache可能会被交换:给你的用户带来痛苦.因此,PHP做了下一个最好的事情:将这个接收的文件放在一个临时文件中.

您可能会问为什么PHP不能被告知首先放入传入文件数据的文件,因此您不必移动它.好吧,这是一个引导问题:PHP尚未将控制权交给脚本,因此脚本无法告诉PHP将文件放在何处.因此,PHP尽其所能:将文件数据放入临时文件中.

现在,您可以将此文件数据保存在RAM磁盘中,以便在需要时提高速度.如果您不介意基础架构成本(例如,维护RAM磁盘设置),这是一种很好的方法.但请注意,这不像PHP在RAM本身中持有它:在那种情况下,PHP容器进程(通常是Apache或其他一些Web服务器)必须有堆来保存文件(它可能不会).在这种情况下,RAM磁盘由内核管理.

  • 是:将[`upload_tmp_dir`](http://php.net/manual/en/ini.core.php#ini.upload-tmp-dir)设置更改为所需的路径. (17认同)
  • @JaiShreeGanesh如果你想将`upload_tmp_dir`变量改为所需的,可公开访问的目录......**不要**.Somone可以简单地将恶意文件发布到您的PHP脚本中,它将最终进入该目录**而无需进行任何健全性检查**. (8认同)
  • 其他框架通常解决这个问题的方法是通过为应用程序提供一个懒惰的可枚举的http部分来避免整个问题.一个更灵活的解决方案,但它也对PHP通常试图避免的应用程序开发人员承担更多责任. (3认同)
  • 我可以更改临时位置吗?或者它是一个固定的位置? (2认同)
  • 非常感谢你的努力 (2认同)

Jom*_*oos 19

写入临时位置的好处是什么,然后将其复制到预定目的地?:

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

  • 请说出"文件移动是原子的"是什么意思?非常感谢您的努力 (4认同)
  • @JaiShreeGanesh原子操作,是一个操作,可以不间断地完成(想想中断,进程调度等).他们要么失败要么成功.元数据更改是原子的.文件重命名就是这种情况. (3认同)
  • 原子意味着全有或全无. (3认同)
  • @JaiShreeGanesh:"原子"是计算机科学中的一个重要概念.有关概述,请参阅维基百科关于[线性化]的文章(https://en.wikipedia.org/wiki/Linearizability). (2认同)

小智 5

另外两个原因:

  1. 如果您因某种原因决定不接受该文件,则会将其存储在临时位置,并且可能会在某个时刻自动删除.

  2. 安全.假设PHP已设置为上传到像/ images这样的Web可访问目录.有人可以上传某种黑客文件,然后执行它.通过首先将文件放在临时目录中(通常不能通过Web访问),PHP允许您首先检查文件.例如,通过处理图像来删除任何可能包含PHP代码的注释.