【问题标题】:Handling too long requests in mod_fcgid在 mod_fcgid 中处理过长的请求
【发布时间】:2014-05-15 20:34:35
【问题描述】:

目标

当我的客户尝试上传的文件太大时,我想向他们显示有意义的消息。

问题

现在,当我尝试发送太大的请求时,我的 mod_fcgid 会抛出 500 Internal Server Error。我不知道如何从以下内容中判断此错误:

  • display_errors 设置为 0 时出现 PHP 错误
  • 请求 uri 太长
  • 错误的重写规则
  • 其他错误配置
  • 完全不同的东西

如果我要在 500 ISE 处理程序中告诉我的客户“嘿,你试图上传太大的文件”,它也会触发以上所有内容,这是没有意义的。

我尝试过的事情

我目前唯一能做的就是使用ErrorDocument 500 /generic-500.php 重定向所有错误。转储 $_SERVER$_REQUEST 并没有显示任何有用的信息。

可以通过以下方式以丑陋的方式绕过问题:

  1. 在表单上创建 AJAX 包装器
  2. 让它单独为这个表单附加自定义标题
  3. 当我被重定向到 500 ISE 时检查此标头

但这很愚蠢,我必须记住对每个上传表单都这样做。

问题

如何在 PHP 中检测 500 ISE 的原因或重新配置我的服务器,以便在收到 POST 请求时检测到 PHP 中的上传过大?

【问题讨论】:

  • 考虑到你想显示有用的错误信息;为什么不直接使用$_FILES['userfile']['size'] > maxSize,如果条件为假则上传文件,否则显示消息?
  • 因为在我开始执行我的 PHP 代码之前,mod_fcgid 接管并自行渲染 500 ISE。

标签: php post file-upload mod-fcgid


【解决方案1】:

转储 $_SERVER$_REQUEST [在 500 错误处理脚本内] 没有显示任何有用的信息。

$_SERVER['CONTENT_LENGTH'] 呢,你检查过吗?如果该值在错误处理脚本中仍然“完整”并且具有客户端最初发送的值,那么可能会继续进行。

除此之外,似乎很难用 PHP 对这样的错误做出反应——首先必须在mod_fcgid 级别进行处理,以便它仍然调用脚本(或任何脚本)以及相关信息;但是从文档中我看不到任何方法。

作为一种解决方法,您可以尝试设置一个不同 ErrorDocument 脚本,专门用于处理您的文件上传的端点脚本 – f.e.通过在 FILES 指令中使用该指令,该指令仅包含您的上传处理脚本。
这样,如果您的“特殊” 500 错误脚本被调用,则很有可能是因为上传的文件太大 - 您可以告诉用户,很可能 他们看到此错误页面的原因是。
当然,您必须尽一切可能确保没有其他原因导致这些脚本可能出现 500 的具体原因 - 正如您已经说过的那样,这有点像 p.i.t.a.也一样,甚至可能无法以完全可靠的方式实现……但也许这是一个开始。

最重要的是,在客户端上传甚至开始之前尝试防止这种情况发生可能是一个好主意 - 向文件上传字段添加maxlength 属性可能不会阻止每个现有的浏览器,但对于那些确实尊重它的人来说,它可能有助于在问题发生之前缓解问题。 (HTML5 已经指定了该属性;虽然我还没有检查过它可以以何种方式与 HTML5 表单验证结合使用,以在这种情况下提醒用户具体的错误原因。)


附带说明:从 HTTP 的角度来看,在这种情况下使用状态码 500 进行回答似乎并不合适 - 413 Request Entity Too Large 存在,恕我直言,应该将其视为 正确 响应在这种情况下。太糟糕了mod_fcgid 不会自动这样做,因为这基本上可以解决问题而无需进一步努力。

【讨论】:

  • 你是对的。我可以使用ErrorDocument 500 /ise.php 将其重定向到脚本,并在其中确实检查$_SERVER[REDIRECT_CONTENT_LENGTH],对于20MB 的测试文件,它包含string(8) "20971705"。另一方面,$_SERVER[CONTENT_LENGTH] 包含string(8) "10483545"。我猜它在途中被截断了。
  • 要明确一点——20MB 文件超出了您的配置允许的上传限制?如果实际限制是 10MB,那么 10483545 非常适合,大约是 9.998MB - 为其余的请求数据(参数和文件名,多部分编码边界,​​可能是一些标头……)添加一点“开销”,并且我们可以假设此时 mod_fcgid 取消请求并将控制权交给错误处理程序。
  • 是的,限制设置为 10MB。
【解决方案2】:

这很奇怪,但您无法知道请求的长度,因为请求因您的服务器中断而未完成。

您可以做的最好的事情是使用相当高的FcgidMaxRequestLen 指令来增加请求正文的大小限制。在您的服务器处理请求且未产生任何 500 服务器错误并到达应用程序后,您可以验证应用程序中的内容并向用户返回有意义的消息。

【讨论】:

    【解决方案3】:

    set_file_buffer($f, $b) 呢?你可以在那里设置缓冲区大小 - 如果你不能让它工作,我会使用输出缓冲区方法来控制它......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-20
      • 1970-01-01
      • 2017-02-05
      • 2020-10-17
      • 1970-01-01
      • 1970-01-01
      • 2019-12-20
      相关资源
      最近更新 更多