【问题标题】:PHP - Posting JSON via file_get_contentsPHP - 通过 file_get_contents 发布 JSON
【发布时间】:2012-07-04 09:26:00
【问题描述】:

我正在尝试将 JSON 内容发布到远程 REST 端点,但是“内容”值在交付时似乎为空。所有其他标头等都被正确接收,并且 Web 服务使用基于浏览器的测试客户端成功测试。

我在下面指定“内容”字段的语法是否有问题?

$data = array("username" => "duser", "firstname" => "Demo", "surname" => "User", "email" => "example@example.com");   
$data_string = json_encode($data);

$result = file_get_contents('http://test.com/api/user/create', null, stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => array('Content-Type: application/json'."\r\n"
. 'Authorization: username:key'."\r\n"
. 'Content-Length: ' . strlen($data_string) . "\r\n"),
'content' => $data_string)
)
));

echo $result;

【问题讨论】:

    标签: php json rest post file-get-contents


    【解决方案1】:

    这是我一直使用的代码,它看起来非常相似(尽管这当然适用于 x-www-form-urlencoded)。 也许你的username:key 需要是base64_encode'd。

    function file_post_contents($url, $data, $username = null, $password = null)
    {
        $postdata = http_build_query($data);
    
        $opts = array('http' =>
            array(
                'method'  => 'POST',
                'header'  => 'Content-type: application/x-www-form-urlencoded',
                'content' => $postdata
            )
        );
    
        if($username && $password)
        {
            $opts['http']['header'] = ("Authorization: Basic " . base64_encode("$username:$password"));
        }
    
        $context = stream_context_create($opts);
        return file_get_contents($url, false, $context);
    }
    

    【讨论】:

    • 如果有人遇到 post-data 编码不正确的问题(字典的每个键都有一个“amp;”开头):将第三行更改为 $postdata = http_build_query($data, '', '&');
    • 这不是发布 JSON,这是发布名称-值对。它没有回答最初的问题,认为它可能有效。
    【解决方案2】:

    问题是关于json,为什么接受的答案是关于x-www-form

    Json 有很多很酷的东西需要解决,比如utf8_encode

    function my_utf8_encode(array $in): array
    {
        foreach ($in as $key => $record) {
            if (is_array($record)) {
                $in[$key] = my_utf8_encode($record);
            } else {
                $in[$key] = utf8_encode($record);
            }
        }
    
        return $in;
    }
    
    
    function file_post_contents(string $url, array $data, string $username = null, string $password = null)
    {
        $data     = my_utf8_encode($data);
        $postdata = json_encode($data);
        if (is_null($postdata)) {
            throw new \Exception('decoding params');
        }
    
        $opts = array('http' =>
            array(
                'method'  => 'POST',
                'header'  => 'Content-type: application/json',
                'content' => $postdata
            )
        );
    
        if (!is_null($username) && !is_null($password)) {
            $opts['http']['header'] .= "Authorization: Basic " . base64_encode("$username:$password");
        }
    
        $context = stream_context_create($opts);
    
        try {
            $response = file_get_contents($url, false, $context);
        } catch (\ErrorException $ex) {
    
            throw new \Exception($ex->getMessage(), $ex->getCode(), $ex->getPrevious());
        }
        if ($response === false) {
    
            throw new \Exception();
        }
    
        return $response;
    }
    

    【讨论】:

    • my_utf8_encode 应该是递归的吗?如果 self::utf8_encode($record) 是一个数组,你应该用 my_utf8_encode($record) 替换它吗?
    • @HelloWorld,你是对的。我刚刚修好了。谢谢
    • file_get_contents 不会抛出 ErrorException (或任何异常),除非您在代码的其他地方运行了自定义错误处理程序。而且你不应该使用utf8_encode - 该函数确实转换为utf-8,但只能从一个特定的字符集。除非您 100% 确定您的数据是 iso-8859-1,否则您应该使用像 mb_convert_encoding() 这样的函数。 (对于实际回答问题仍然 +1!)
    【解决方案3】:

    之前的回应

    function file_post_contents($url, $data, $username = null, $password = null) {
    $postdata = http_build_query($data);
    
    $opts = array('http' =>
        array(
            'method'  => 'POST',
            'header'  => 'Content-type: application/x-www-form-urlencoded',
            'content' => $postdata
        )
    );
    
    if($username && $password)
    {
        $opts['http']['header'] = ("Authorization: Basic " . base64_encode("$username:$password"));
    }
    
    $context = stream_context_create($opts);
    return file_get_contents($url, false, $context);}
    

    不正确。此功能有时有效,但如果您不使用 application/x-www-form-urlencoded 的 Content-type 并传入用户名和密码,它会不准确并且会失败。

    它对作者有用,因为 application/x-www-form-urlencoded 是默认的内容类型,但他对用户名和密码的处理会覆盖之前的内容类型声明。

    这里是修正后的函数:

    function file_post_contents($url, $data, $username = null, $password = null){
    $postdata = http_build_query($data);
    
    $opts = array('http' =>
        array(
            'method'  => 'POST',
            'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
            'content' => $postdata
        )
    );
    
    if($username && $password)
    {
        $opts['http']['header'] .= ("Authorization: Basic " . base64_encode("$username:$password")); // .= to append to the header array element
    }
    
    $context = stream_context_create($opts);
    return file_get_contents($url, false, $context);}
    

    注意这一行: $opts['http']['header' .= (点等于追加到数组元素。)

    【讨论】:

      猜你喜欢
      • 2013-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-08
      相关资源
      最近更新 更多