2012-07-02 45 views
2

根据documentation,php://input并不总是包含HTTP请求主体。在开始阅读之前可以知道php://输入是否包含数据?

我有一些代码的脚本启动时始终打开流,将其提供给用户的应用程序:

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

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

请求正文不可用。

我的问题是:

  • 如果流为空,feof()回报falsefread()没有被调用;
  • 我不能fread() 1字节,然后fseek(),因为这个流不支持寻求;
  • 我无法打开另一个php://input并尝试事先读取它,因为我们不能依赖此流可以多次使用;
  • 出于性能原因,我不想在将用户应用程序交给用户应用程序之前将其盲目复制php://inputphp://temp

因此,是可以告诉php://input是否包含fopen()后的数据正确,但在此之前任何fread()

回答

1

我发现的解决方案是创建代表该请求的身体,并从这个类阅读,而不是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字节来隐藏这种复杂性。

0

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

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

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

相关问题