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

问题描述 投票:0回答:15

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

file_get_contents('php://input')

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

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

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

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

php json rest curl restful-architecture
15个回答
44
投票

正如 在网络其他地方 所指出的那样,

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


12
投票

确保没有重定向。

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

检查重定向的一种快速方法是使用 curl 检查 url。在命令行上:

curl -IL http://example.com/api


10
投票

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

--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 设置:

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

    file_get_contents
    只有在您的 PHP 设置中将
    allow_url_fopen
    设置为 true 时才有效。这是在 php.ini 中设置的内容,但您也可以在运行时通过在其他代码之前按照以下代码行编写内容来更改设置:

    ini_set("allow_url_fopen", true);
    

6
投票

我也有这个错误,我的解决办法是把数据格式改成原始的。

我从 php doc 那里得到它说

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


5
投票

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

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"];

5
投票

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

在您的示例 curl 调用中:
把 s 放在 http 之后,如下所示:

curl -i -X PUT -d '{"address":"Sunset Boulevard"}' https://localhost/clients/ryan


2
投票

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


2
投票

随意编辑

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;
}

2
投票

FWIW 我正在使用 Postman 发送值。在 Body 选项卡上,我应该使用“Raw”选项卡发送 json {"ID":1234,"Type":"Blah"} 但我愚蠢地使用 form-data 选项卡将 Key/Value 放入其中使 php://input 结果为 NULL。一旦我切换到使用带有 JSON 的原始选项卡,然后一切都按预期工作。


1
投票

正确的函数调用是:

file_get_contents("php://input");

您应该收到一条错误消息,指出

php:input
不存在...

在任何情况下,

PUT
旨在将文件上传到服务器,假设服务器支持它。通常,您会使用
POST
和适合内容的
Content-Type
标题。


1
投票

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

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

0
投票

我看到问题了,

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

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

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


0
投票
{
  "action":"get_events_by_category",
  "category_id":2
}

您的行字符串数据必须是双引号 "" 而不是单引号 ''


0
投票
{"id": 1, "username":"surecoder", "password":"surecoder"}

您的键和值字符串数据必须是双引号 "" 而不是单引号 ''


0
投票

检查您的 CSRF 权限。这让我明白了——我希望将 Webhooks 发布到服务器,但忘记关闭 CSRF 要求,因此服务器(正确地)无法发布到我的页面。简单的问题,但如果没有重定向,请检查您是否可以将内容发布到您的页面。

© www.soinside.com 2019 - 2024. All rights reserved.