1

这是一个简单的文件上传表单 HTML。

<form enctype="multipart/form-data" action="upload.php" method="POST">
    Send this file: <input name="userfile" type="file" />
    <input type="submit" value="Send File" />
</form>

php 文件也很简单。

<?php
die();

如您所见,PHP 脚本在服务器端什么都不做。但是当我们上传一个大文件时,这个过程仍然需要很长时间。

我知道,我的 PHP 代码将在 POST 过程结束后执行。PHP必须在解析第一行代码之前准备名为 $_POST 和 $_FILES 的数组。

所以我的问题是:PHP(使用 Apache 或 Nginx)可以在 POST 请求完成之前检查 HTTP 标头吗?

例如,一些 PHP 扩展或 Apache 模块。

有人告诉我 Python 或 node.js 可以解决这个问题,只是想知道 PHP 是否可以。

谢谢。

================ 更新1 ================

我的目标是尝试阻止一些意外的文件上传请求。例如,我们生成了一个唯一令牌作为 POST 目标 URL(如http://some.com/upload.php?token=268dfd235ca2d64abd4cee42d61bde48&t=1366552126)。在服务器端,我的代码如下:

<?php
define(MY_SALT, 'mysalt');
if (!isset($_GET['t']) || !isset($_GET['token']) || abs(time()-$_GET['t'])>3600 || md5(MY_SALT.$_GET['t'])!=$_GET['token']) {//token check
    die('token incorrect or timeout');
}
//process the file uploaded
/* ... */

代码看起来很有意义:-P 但不能像我预期的那样节省带宽。原因是 PHP 代码运行太晚,我们无法在文件上传完成之前检查令牌。如果有人在 url 中上传没有正确令牌的文件,我的服务器的网络和 CPU 仍然浪费。

欢迎任何建议。非常感谢。

4

2 回答 2

1

答案总是肯定的,因为这是开源的。但首先,一些背景知识:(我只讲nginx,Apache也差不多。)

上传请求不会立即发送到您的 PHP 后端——nginx 会缓冲上传正文,因此您的 PHP 应用程序不会占用 100MB 的 RAM 等待某人通过 300 波特调制解调器上传。不利的一面是,您的应用在完成或大部分完成上传(取决于client_body_buffer_size)之前甚至不会发现上传。

但是您可以编写一个模块来挂钩到 nginx 内部的不同“阶段”。当标头完成时,将调用其中一个钩子。您可以在 LUA 中编写模块,但它仍然相当复杂。可能有一个模块会通过 HTTP 将“预上传”挂钩发送到您的脚本。但这对性能来说并不是很好。

您很可能甚至不需要模块。nginx.conf 文件可以做你需要的。(即根据标头将请求路由到不同的脚本,或根据标头返回不同的错误代码。)请参阅此页面以获取标头检查的示例(尤其是“WordPress w/ W3 Total Cache using Disk (Enhanced)”):http:// /kbeezie.com/nginx-configuration-examples/

阅读文档,因为一些常见的标头检查需求已经有自己的指令(即client_max_body_size,如果 Content-Length 标头太大,将拒绝请求。)

于 2013-04-21T00:53:34.050 回答
1

水平上没有解决方案HTTP,但水平上是可能的TCP。请参阅我在另一个问题中选择的答案:

通过 PHP 或 Apache 中断从服务器端上传的 HTTP 文件

于 2013-05-03T03:13:32.557 回答