file_get_contents('php://input') 总是返回一个空字符串

Posted

技术标签:

【中文标题】file_get_contents(\'php://input\') 总是返回一个空字符串【英文标题】:file_get_contents('php://input') always returns an empty stringfile_get_contents('php://input') 总是返回一个空字符串 【发布时间】:2013-10-09 10:20:26 【问题描述】:

我正在构建一个 php RESTful API,遵循 this 教程。以下函数在使用 'put' 方法时应返回随请求发送的数据,但每次都返回 null:

file_get_contents('php://input')

我什至已经下载并测试了教程中的完整代码示例,但它仍然返回 null。

我正在使用 cURL 和以下命令来测试 'put' 方法:

curl -i -X PUT -d '"address":"Sunset Boulevard"' http://localhost/clients/ryan.

我在这上面浪费了好几天,仍然没有得到它来读取 json 数据。我做错了什么?

【问题讨论】:

您不会多次阅读php://input 的消息吗?请参阅此处的注意 - php.net/manual/… @Phil Nope,我只读过一次。 【参考方案1】:

作为noted elsewhere on the web,如果请求被重定向,php://input 内容不会通过。也许您的 Web 服务器具有从以 www 开头的 URL 到不带 www 的 URL 的重定向,或者从使用 HTTP 的 URL 到使用 HTTPS 的 URL 的重定向。检查您的网络服务器日志以验证这一点,并采取相应措施以避免在调用网络服务时重定向。

【讨论】:

我不相信这可能是我的问题,但 curl 的测试证实确实存在从 example.com/test 到 example.com/test/ 的 301(添加了一个斜杠):facepalm : 是的,你拯救了我的一天。一直在互联网上搜索并找到了这个。我的通过 htaccess 从 http:// 重定向到 https://。非常感谢。 你是救生员。我在名为“extraction”的文件夹中创建了一个 index.php 文件,并在 Postman 中将 URL 提供为http://my-project/extraction。将 index.php 更改为 extract.php,并将 URL 更改为 http://my-project/extraction/extract.php 为我解决了这个问题。我推断当应用程序 URL 中仅提供文件夹名称时,文件夹中的任何 index.php 文件都会发生 HTTP 重定向 为你加星。非常感谢 你真是个救命恩人!!谢谢朱利奥【参考方案2】:

首先,我能够运行这段代码并且运行良好:

--Terminal---------
//I ran this curl request against my own php file:
curl -i -X PUT -d '"address":"Sunset Boulevard"' http://localhost/test.php


--PHP--------------
//get the data
$json = file_get_contents("php://input");

//convert the string of data to an array
$data = json_decode($json, true);

//output the array in the response of the curl request
print_r($data);

如果这不起作用,请检查控制台是否有错误和您的 php 设置:

    您使用的 curl url,确保该 url 确实有效并且没有返回错误。 打开另一个终端/控制台窗口并运行tail -f /path/to/the/php/log/file,这样您就可以实际看到这些 php 调用的输出。 通常人们会收到此错误:file_get_contents(file://input): failed to open stream: no suitable wrapper could be found,这可能表示“file://input”字符串的拼写错误或allow_url_fopen 在 php 中被禁用的事实(如果不确定,请参阅 #5) 确保您的代码是正确的,我的意思是确保您没有输入不正确的参数和东西......在 netbeans 中不一定会加下划线的东西。

    请记住,file_get_contents 仅在您的 PHP 设置中将 allow_url_fopen 设置为 true 时才有效。这是在 php.ini 中设置的内容,但您也可以在运行时更改设置,方法是在其他代码之前按照以下代码行编写一些内容:

    ini_set("allow_url_fopen", true);
    

【讨论】:

我拿走了你的代码并运行了它,这就是我得到的全部:C:\Users\Igor\Desktop\curl>curl -i -X PUT -d '"address":"Sunset"' http://local host/server.php HTTP/1.1 200 OK Date: Thu, 03 Oct 2013 07:53:54 GMT Server: Apache/2.2.21 (Win64) PHP/5.3.8 X-Powered-By: PHP/5.3.8 Content-Length: 0 Content-Type: text/html 仍然没有。 allow_url_fopen 也开启了。 尝试在没有 -i 标志的情况下运行 curl 并添加 -v 标志以查看发生了什么。我几乎从不在 Windows 上运行 *amp 堆栈,所以那里可能会发生一些奇怪的事情。另外,请尝试在该响应中输出任意字符串,以确保您完全可以看到输出。另外,您是否查看了您的 php_log 以查看是否发生了任何错误? 我用-v 替换了-i 标志,仍然得到相同的结果。我还添加了 print_r('error') 以查看它是否会显示并且确实会显示,但 $data 仍然是空的。日志文件也是空的。也许我应该重新安装 wamp??? 我什至在另一台机器上安装了 XAMP 和 WAMP 并运行了这段代码,我得到了空字符串。使用-v 标志向我显示所有字节都已发送。我不明白。 你还没有回答关于查看你的php错误日志的问题【参考方案3】:

确保没有重定向。

file_get_contents(php://input) 不会通过重定向传递正文内容。

检查重定向的一种快速方法是使用 curl 检查 url。在命令行上: curl -IL http://example.com/api

【讨论】:

这真的很有帮助。 301 重定向可以更改为 308(如果需要重定向并且要求允许)。请参阅 MDN developer.mozilla.org/en-US/docs/Web/HTTP/Status/301 上的文档“因此,建议仅将 301 代码用作 GET 或 HEAD 方法的响应,而将 308 永久重定向用于 POST 方法,因为在此状态下明确禁止更改方法。 " 我的 http 请求被重定向到 https,因此删除了表单内容。谢谢提示【参考方案4】:

对我来说,这个问题突然开始了。 我已经安装了 ssl 证书。 当我检查它向我显示 301 的响应代码时,我意识到并更改了http://到https://并得到了所有请求返回 file_get_contents('php://input')。

在您的示例 curl 调用中: 在 http 后面加上 s 如下图:curl -i -X PUT -d '"address":"Sunset Boulevard"' https://localhost/clients/ryan

【讨论】:

【参考方案5】:

我也遇到了这个错误,我的解决方案是将数据格式更改为原始格式。

我是从php doc 那里得到的

php://input 不适用于 enctype="multipart/form-data"

【讨论】:

【参考方案6】:

我用这段代码写了一个头文件:

if($_SERVER["REQUEST_METHOD"] == "POST" && $_SERVER["CONTENT_TYPE"] == "application/json")

  $data = file_get_contents("php://input", false, stream_context_get_default(), 0, $_SERVER["CONTENT_LENGTH"]);
  global $_POST_JSON;
  $_POST_JSON = json_decode($_REQUEST["JSON_RAW"],true);

  // merge JSON-Content to $_REQUEST 
  if(is_array($_POST_JSON)) $_REQUEST   = $_POST_JSON+$_REQUEST;

它检查正确的内容类型,它只读取与 Content-Length 标头中指定的一样多的帖子输入。 当接收到一个有效的 JSON 时,它会创建一个全局数组 $_POST_JSON。

因此,您可以像使用 url 编码的 POST 值一样使用 JSON 内容。

例子:

 echo $_POST_JSON["address"];
 // or
 echo $_REQUEST["address"];

【讨论】:

带有所有参数的函数示例对我很有用:$data = file_get_contents("php://input", false, stream_context_get_default(), 0, $_SERVER["CONTENT_LENGTH"]);【参考方案7】:

我遇到了同样的问题。 最终,我发现问题是在客户端我没有对 json 对象进行字符串化(之前我使用了 nodejs 服务器,还可以)。 一旦我这样做了,我就收到了 $_POST 中的数据(不是 json),作为常规参数。

【讨论】:

【参考方案8】:

FWIW 我使用 Postman 发送值。在正文选项卡上,我应该使用“原始”选项卡发送 json "ID":1234,"Type":"Blah" 但我愚蠢地使用表单数据选项卡输入键/值使 php://input 结果为 NULL。一旦我切换到使用带有 JSON 的原始选项卡,那么一切都按预期工作。

【讨论】:

【参考方案9】:

正确的函数调用是:

file_get_contents("php://input");

您应该会收到一条错误消息,指出 php:input 不存在...

无论如何,PUT 用于将文件上传到服务器,假设服务器支持它。通常你会使用POST 和适合内容的Content-Type 标头。

【讨论】:

对不起,我使用的是file_get_contents('php://input'),我已经编辑了问题。 再次抱歉,来晚了,我累了 查看manual 中的注释,看起来PUT 请求并不适合这个。请改用POST 刚刚做了。它再次返回 null。 但是...null 不是file_get_contents 的有效返回值。它可以返回一个字符串,或false。从不null。你确定你没有错别字吗?比如你用来存储字符串的变量名?【参考方案10】:

在 Windows 上,“单“双”引号的组合似乎不起作用。在您的 json 数据中使用转义引号(如下所示)& 它应该可以工作

curl -X PUT -d "\"address\":\"Sunset Boulevard\"" http://localhost/clients/ryan

【讨论】:

【参考方案11】:

随意编辑

function getPostObject() 
    $str = file_get_contents('php://input');
    $std = json_decode($str);
    if ($std === null) 
        $std = new stdClass();
        $array = explode('&', $str);
        foreach ($array as $parm) 
            $parts = explode('=', $parm);
            if(sizeof($parts) != 2)
                continue;
            
            $key = $parts[0];
            $value = $parts[1];
            if ($key === NULL) 
                continue;
            
            if (is_string($key)) 
                $key = urldecode($key);
             else 
                continue;
            
            if (is_bool($value)) 
                $value = boolval($value);
             else if (is_numeric($value)) 
                $value += 0;
             else if (is_string($value)) 
                if (empty($value)) 
                    $value = null;
                 else 
                    $lower = strtolower($value);
                    if ($lower === 'true') 
                        $value = true;
                     else if ($lower === 'false') 
                        $value = false;
                     else if ($lower === 'null') 
                        $value = null;
                     else 
                        $value = urldecode($value);
                    
                
             else if (is_array($value)) 
                // value is an array
             else if (is_object($value)) 
                // value is an object
            
            $std->$key = $value;
        
        // length of post array
        //$std->length = sizeof($array);
    
    return $std;

【讨论】:

当你想调用$post->p1 时,json_decode(file_get_contents('php://input'))p1=1&p2=blabla$p3=false 等参数时返回空或 null。 例如:JQUERY $.post(url, $('form').serialize()); 因为它需要 JSON 类型 你真的应该采取“回归早期原则”,大多数elseelse if可以避免,缩进可以显着变平,只有在极少数情况下你才需要else或@987654328 @ - 改变你的方法:)【参考方案12】:

我看到了问题,

您需要在请求url的末尾添加filename.php或需要重写.htaccess文件中的服务器规则来解决这个问题。

curl -i -X PUT -d '"address":"Sunset Boulevard"' http://localhost/clients/ryan/filename.php

用适当的文件名替换 filename.php。 :)

【讨论】:

【参考方案13】:

  "action":"get_events_by_category",
  "category_id":2

您的行字符串数据必须是双引号 "" 不能使用单个 ''

【讨论】:

以上是关于file_get_contents('php://input') 总是返回一个空字符串的主要内容,如果未能解决你的问题,请参考以下文章

php中的file_get_contents或curl?

file_get_contents 通过 php 失败,通过浏览器工作

php PHP Image出力(file_get_contents)

C# 相当于 file_get_contents (PHP)

php file_get_contents 绕过

php file_get_contents抓取