2

根据文档php://input并不总是包含 HTTP 请求正文。

我有一些代码总是在脚本启动时打开流,以使其对用户应用程序可用:

$stream = fopen('php://input', 'rb');

如果用户应用程序尝试从空流中读取Content-Length > 0,我希望我的库抛出异常:

请求正文不可用。

我的问题是:

  • 如果流为空,则在未调用时feof()返回;falsefread()
  • 那我不能fread()1 字节fseek(),因为这个流不支持搜索;
  • 我无法打开另一个php://input并尝试事先从中读取,因为我们不能多次依赖此流可用;
  • 出于性能原因,我不想在将手交给用户应用程序之前php://input盲目复制。php://temp

因此,是否可以判断是否在 之后但在 any 之前php://input包含数据fopen()fread()

4

2 回答 2

2

我找到的解决方案是创建一个代表请求正文的类,并从这个类中读取而不是php://input直接读取:

class RequestBody
{
    protected $firstByte;

    protected $isEmpty;

    public function __construct($stream)
    {
        $this->firstByte = fread($stream, 1);
        $this->isEmpty = ($this->firstByte === '');

        // ...
    }

    public function isEmpty()
    {
        return $this->isEmpty;
    }

    public function read($length)
    {
        // ...
    }
}

$body = new RequestBody(fopen('php://input', 'rb'));

类构造函数读取流的第一个字节,将其存储以供以后使用,并立即知道流是否为空。

read()$length - 1通过在第一次调用它时返回第一个字节 + 字节来隐藏这种复杂性。

于 2012-08-09T09:02:53.857 回答
0

“使用 php://input 打开的流只能读取一次;该流不支持查找操作。”

http://php.net/manual/en/wrappers.php.php

对我来说,这表明它是一个老式的只读流。您无法寻找和测试它是文件的结尾还是长度。

于 2012-07-02T21:57:51.417 回答