如何在PHP中读取使用CURL PUT发送的数据?我有POST和GET工作,但PUT不起作用。我发现你必须使用php://input
读取数据。我如何解析数据?
这是PUT文件test15.php:
<?php
// CURL PUT Test
$browser = $_SERVER['HTTP_USER_AGENT'];
$url = 'http://localhost/curltest/test15_put.php';
// echo "URL: $url <br>";
$headers = array(
"Accept: application/json"
);
// set post fields
$post = array(
'firstname' => 'John',
'lastname' => 'Doe',
'email' => 'email@domain.com',
'notes' => 'Test user to test CURL PUT request'
);
$post2 = json_encode($post);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_USERAGENT, $browser);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, True);
$response = curl_exec($curl);
echo "<pre>";
print_r($response);
echo "</pre>";
?>
这是接收文件test15_put.php:
<?php
parse_str(file_get_contents("php://input"), $post_vars);
$firstname = $post_vars['firstname'];
$lastname = $post_vars['lastname'];
$value = array('firstname' => $firstname, 'lastname' => $lastname);
echo json_encode($value);
?>
这是我得到的数据:
Array
(
[--------------------------f7bdbb5224ed4e09
Content-Disposition:_form-data;_name] => "firstname"
John
--------------------------f7bdbb5224ed4e09
Content-Disposition: form-data; name="lastname"
Doe
--------------------------f7bdbb5224ed4e09
Content-Disposition: form-data; name="email"
email@domain.com
--------------------------f7bdbb5224ed4e09
Content-Disposition: form-data; name="notes"
Test user to test CURL PUT request
--------------------------f7bdbb5224ed4e09--
)
是否有其他方法可以发送数据并获得更好的响应?
更新 2016-11-29 这是返回的$ GLOBALS数据:
[GLOBALS] => Array
*RECURSION*
[browser] => Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36
[url] => http://localhost/milk/test15_put.php
[headers] => Array
(
[0] => Accept: application/json
)
[post] => Array
(
[firstname] => John
[lastname] => Doe
[email] => email@domain.com
[notes] => Test user to test CURL PUT request
)
[post2] => {"firstname":"John","lastname":"Doe","email":"email@domain.com","notes":"Test user to test CURL PUT request"}
[curl] => Resource id #2
[response] =>
更新3 - 2016-12-08
我尝试使用 S.Pinkus 中的代码。我使用运行XAMPP和PHP 5.6.21的Windows PC。我仍然得到返回的空数组,而不是我需要的值。我也编写我的PHP代码并从浏览器运行,而不是命令行。这是我修改后的 S.Pinkus 代码和输出:
<?php
// CURL PUT Test
$browser = $_SERVER['HTTP_USER_AGENT'];
$url = 'http://localhost/curltesting/test16_put.php';
// echo "URL: $url <br>";
$payload = ['x' => 1, 'y' => 2];
// PUT JSON. \$_POST is not set server side. php://input gives the JSON payload.
print "<br>### TEST 1 (application/json):<br>";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, True);
$response = curl_exec($curl);
var_dump($response);
// PUT form data. \$_POST is set by PHP server side.\n";
echo "<br>### TEST 2 (multipart/form-data):<br>";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, []);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, True);
$response = curl_exec($curl);
var_dump($response);
?>
这是test16_put.php代码:
<?php
ini_set('log_errors', true);
ini_set('display_errors', true);
ini_set('error_reporting', E_ALL);
echo "\n### \$_POST: <br>";
echo "<pre>";
print_r($_POST);
echo "</pre><br>";
echo "<br><br>### Request Body: <br>";
echo file_get_contents('php://input') . "<br>";
?>
这是我得到的输出:
### TEST 1 (application/json):
string(89) " ### $_POST:
Array
(
)
### Request Body:
{"x":1,"y":2}
"
### TEST 2 (multipart/form-data):
string(304) " ### $_POST:
Array
(
)
### Request Body:
--------------------------8f21ab28aa12c814 Content-Disposition:
form-data; name="x" 1 --------------------------8f21ab28aa12c814
Content-Disposition: form-data; name="y" 2
--------------------------8f21ab28aa12c814--
"
似乎我只获得Request Body字符串中返回的所需数据,而没有其他地方......
答案 0 :(得分:2)
问题&#34;如何通过PHP&#34; 中的HTTP PUT请求读取数据,答案是,有两种(正常)方式。您使用哪种方式取决于您发送数据的方式 - 特别是您发送的Content-Type
:
如果您将CURLOPT_POSTFIELDS
与数组一起使用,则Curl将发送Content-Type: multipart/form-data
的请求。 PHP将识别此Content-Type
并将正文解析为$_POST超全局数组(无论它是PUT还是POST请求)。一旦PHP完成了这个解析,你就无法通过php://input
anymore来检索正文的内容 - 我不完全确定为什么会这样,但是因为它&#39 ;在$ _POST中没有理由想要。
但是如果你只是想发送一个任意的主体(比如说JSON或TXT或XML ......)将数据放在CURLOPT_POSTFIELDS
中作为一个字符串(你也可以在那里放一个文件的引用但是这超出了问题的范围),并适当地设置Content-Type
。 PHP 赢了填充$_POST
,您阅读数据的方式是php://input
更新:示例:
(旁白:通过以下测试,我发现PHP(5.6无论如何)将解析application/json
个有效负载到$ _POST。但在这种情况下,它仍然会离开php://stdin
所以你可以通过任何一种方法检索一个JSON有效载荷。这必须是一个仅限于application/json
有效载荷的便利,因为其他有效载荷不会明显扩展到一个数组......)。
这是一个测试客户端( curl-put-debug-script.php ):
<?php
isset($argv[1]) or die("Usage: {$argv[0]} <URL>\n");
$payload = ['x' => 1, 'y' => 2];
// PUT JSON. \$_POST is not set server side. php://input gives the JSON payload.
print "\n### TEST 1 (application/json):\n";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $argv[1]);
curl_setopt($curl, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, True);
$response = curl_exec($curl);
var_dump($response);
// PUT form data. \$_POST is set by PHP server side.\n";
print "\n### TEST 2 (multipart/form-data):\n";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $argv[1]);
curl_setopt($curl, CURLOPT_HTTPHEADER, []);
curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, True);
$response = curl_exec($curl);
var_dump($response);
这是一个简单的测试终点,你可以进行调试( curl-debug-svr.php ):
<?php
ini_set('log_errors', true);
ini_set('display_errors', true);
ini_set('error_reporting', E_ALL);
print "\n### \$_POST:\n";
print_r($_POST);
print "### Request Body:\n";
print file_get_contents('php://input') . "\n";
现在,运行服务器,并使用这样的测试脚本点击它 - 假设您在当前工作目录中有两个脚本:
php -S 127.0.0.1:8000 2>/dev/null &
php curl-put-debug-script.php "http://127.0.0.1:8000/curl-debug-svr.php"
给出以下内容:
### TEST 1 (JSON):
string(81) "
### $_POST:
Array
(
[x] => 1
[y] => 2
)
### Request Body:
{"x":1,"y":2}
"
### TEST 2 (multipart/form-data):
string(68) "
### $_POST:
Array
(
[x] => 1
[y] => 2
)
### Request Body:
"
这表明php://stdin
没有为multipart / form-data返回任何内容(即,当你给CURLOPT_POSTFIELDS
数组时)。
更新:解决您的代码示例
简而言之:
Accept: application/json
标题。在这种情况下,这没有任何影响。如果您要发送JSON,则需要设置Content-Type: application/json
。但是你没有在你的例子中发送JSON。curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
)。执行此操作时,您必须从$_POST
超级全局读取数据。您无法(或至少your not supposed)从stdin://input
读取。$post_var
。关于尝试parse_str()
多部分/表单数据编码主体的权利。但我不确定为什么std://input
会返回任何内容。让我想知道你使用的PHP版本。