PHP POST和执行大文件上传

3
我有以下PHP文件:
  • fileUploadForm.php
  • handleUpload.php
fileUploadForm包含以下输出:
  • 如果有,输出 $_SESSION['errorMessage']
  • 输出一个上传文件的表单,该表单提交到 handleUpload.php
handleUpload.php 执行以下操作:
  • 验证会话(如果验证失败,则重定向到登录页面)
  • 验证文件(如果验证失败,则设置 $_SESSION ['errorMessage'])
  • 扫描病毒文件
  • 移动文件
  • 更新数据库
脚本在上传大文件时出现问题。 为测试目的,我已将所有关于文件上传的php.ini设置都设置得非常大。 因此,我不认为这是配置问题。
以下行为让我感到困惑:
  • 当我观察tmp中的文件增长时,文件上传继续进行,即使超过了设置的max_input_time。 我的理解是,一旦超过max_input_time,脚本将终止,进而文件上传也将终止。 你对为什么不会发生这种情况有什么想法吗?

  • 如果我在上传文件的过程中停止并刷新fileUploadForm(而不是重新提交它),则脚本将输出与在handleUpload中设置的与文件验证相关的错误消息。 这似乎表明即使文件上传未完成,handleUpload中的代码行也正在执行。 PHP是否异步执行脚本并接收表单数据? 我本来以为脚本会等到接收到所有表单数据后再执行任何代码。 但是我看到的行为与这个假设相矛盾。 数据POST /脚本执行的顺序是什么?

  • 当max_input_time和其他配置值都设置得非常大以进行测试时,非常大的上传将完成。 但是,脚本的其余部分似乎就死了。 即病毒扫描和文件移动从未发生,数据库更新也没有。 我已经为脚本中的每个操作设置了错误处理,但没有抛出任何错误。 页面似乎已经死了。 有关为什么会发生这种情况/如何捕获此类错误的任何想法吗?

谢谢。 Kate
1个回答

0

你第二个问题中的这句话(至少部分地)回答了其他两个问题:

I would have thought that the script would wait until all form data was received before executing any code.

为了使PHP能够处理所有输入数据,Apache(或者您正在使用的任何HTTP服务器)将首先等待文件上传完成,然后才会处理PHP脚本。因此,在文件上传过程完成后,PHP的max_input_time检查才会发挥作用。
现在,在这种情况下,您可能会问为什么您的病毒扫描、文件移动和任何其他脚本程序没有运行,因为与PHP相关的任何计时器都应该从脚本的执行开始,而这应该是在接收到所有输入数据之后发生的。好吧,这应该是这样的,老实说-我的想法有点靠不住,但是...要么超出了其他限制,要么脚本是由请求启动的,但是被httpd暂停以准备好继续进行,并且在此期间某些计数器可能会过期。
我不知道如何回答您的第二个问题,因为刷新意味着所有数据都将重新POST并且应该重新处理。我怀疑您不会做另一件事-只是加载handleUpload.php而不重新提交表单,但这是我应该提到的可能性。第二次猜测是,如果第一个请求意外终止,则在第二次请求中会发生一些垃圾回收和/或恢复过程。

希望这能稍微澄清一下。


我只是在刷新fileUploadForm.php,而不是实际重新提交它。但现在它包含在handleUpload中设置的会话信息。因此,一些代码正在执行。并且它正在上传整个文件到tmp之前执行。 - user480029
PHP文档在这方面似乎不一致。它像你在答案的第一部分中所述定义了max_input_time:“脚本允许解析输入数据(如POST和GET)的最长时间(以秒为单位)。它是从服务器接收所有数据到脚本执行开始的时间计算的”(即计数在上传完成后开始)。但在故障排除部分中,它指出如果max_input_time不够高,则某些文件上传将无法完成。但无论哪种方式,我都看到文件上传继续进行,一些脚本执行,然后失败。 - user480029
问题是你所说的“只刷新”是什么意思 - 你是在浏览器地址栏中按下回车键还是按下F5(或点击刷新)?如果你是做第二种情况,那么浏览器会询问你是否要重新提交表单数据,并且除非你确认,否则不允许你继续。如果你是做第一种情况,那么...只有会话数据存在是完全正常的。 - Narf
@ Narf 我没有重新提交表单。我正在加载fileUploadForm,而不是handleFileUpload。会话数据存在的不寻常之处在于它是在handleUpload文件中设置的,而这些行在php同步处理并且文件上传/POST尚未完成时不应该被执行。也就是说,我试图理解脚本为什么失败以及为什么在失败的地方失败(有时是在验证代码之后)。 - user480029

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接