php://input 在PHP5.6.16中只能读取一次

php://input 在PHP5.6.16中只能读取一次,php,php-stream-wrappers,Php,Php Stream Wrappers,声明流以php://input 支持seek操作,从PHP5.6开始可以多次读取,但我无法让它工作。下面的示例清楚地表明它不起作用: <!DOCTYPE html> <html> <body> <form method="post"> <input type="hidden" name="test_name" value="test_value"> <input type="submit"> </form> &l

声明流以php://input 支持seek操作,从PHP5.6开始可以多次读取,但我无法让它工作。下面的示例清楚地表明它不起作用:

<!DOCTYPE html>
<html>
<body>
<form method="post">
<input type="hidden" name="test_name" value="test_value">
<input type="submit">
</form>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST')
{
    $input = fopen('php://input', 'r');
    echo 'First attempt: ' . fread($input, 1024) . '<br>';
    if (fseek($input, 0) != 0)
        exit('Seek failed');
    echo 'Second attempt: ' . fread($input, 1024) . '<br>';
}
?>
</body>
</html>
php://input 溪流

  • 成功读取
  • 成功倒带(fseek成功)
  • 读不成功

  • 我做错什么了吗?

    另一种方法可能是每次打开输入流,而不是倒带和查找

    $input = fopen('php://input', 'r');
    echo 'First attempt: ' . fread($input, 1024) . '<br>';
    $input2 = fopen('php://input', 'r');
    echo 'Second attempt: ' . fread($input2, 1024) . '<br>';
    

    如果您正在发送json。

    使用
    php://input
    我建议您阅读该流并将其保存到另一个流中,以避免意外行为

    您可以使用
    php://memory
    以创建一个类似文件流的包装器,它将为您提供与
    php://input
    应该没有所有恼人的行为

    示例:

    <?php
    
    $inputHandle = fopen('php://memory', 'r+');
    
    fwrite($inputHandle, file_get_contents('php://input'));
    
    fseek($inputHandle, 0);
    
    $first1024Bytes = InputReader::instance()->seek(0)->read(1024);
    $next1024Bytes = InputReader::instance()->read(1024);
    
    $phpInput = InputReader::instance()->readAll();
    
    用法(全部读取):

    <?php
    
    $inputHandle = fopen('php://memory', 'r+');
    
    fwrite($inputHandle, file_get_contents('php://input'));
    
    fseek($inputHandle, 0);
    
    $first1024Bytes = InputReader::instance()->seek(0)->read(1024);
    $next1024Bytes = InputReader::instance()->read(1024);
    
    $phpInput = InputReader::instance()->readAll();
    

    由于手册中有大量的例外情况,并且缺乏可移植性,我建议在第一次阅读后保存结果。在此之后,您可以根据结果查找您想要的内容(并且不必将其保存到文件-
    php://memory
    应该这样做。)@H2Ooooo谢谢你,我放弃了“修复”这个问题,并以一个计划结束,以避免像你建议的那样在我未来的所有项目中多次阅读输入。如果你把你的评论转换成一个答案,我会接受。不客气-给我一点时间,我会得到一个答案。是的,我已经注意到它在这种情况下是有效的,但它不适合我,因为我使用的是“zend diactoros”组件而不是直接流访问(我的示例被简化以避免混淆)。这个组件使用(string)$request->getBody()抽象PHP输入流,所以我真的不想绕过zend diactoros手动打开流。