最近一直在写接口,顺便把 php 输入输出流相关知识点学习了一遍php
php://input 数据输入流存放着 post 请求发送过来的原生数据,但 Content-Type:multipart/form-data(上传文件或图片的表单)的数据则不会载入其中,其余类型:html
application/x-www-form-urlencode foo1=bar1&foo2=bar2 普通的表单数据json
application/json {"foo1":"bar1", "foo2":"bar2",}数组
application/xml <xml version="1.0"><data><foo1>bar1</foo1><foo2>bar2</foo2></data>服务器
都会被载入其中app
$HTTP_RAW_POST_DATA 中的内容与 php://input 并没有区别,一样没法识别 curl
Content-Type:multipart/form-data 的请求数据,且默认状况下它与 $_POST 互斥,即若请求数据格式能够填充至 $_POST 中去,即使它也能识别,也不会填充数据,好比 application/x-www-form-urlencode 类型的请求数据, php://input $_POST 和 它都能识别,但 $_POST 填充后默认配置下它是不会被填充的,除非修改 php.ini 文件将 always_populate_raw_post_data 配置参数使能,即只要能识别,就填充,无论 $_POST 是否被填充ide
php 能自动识别处理填充到 $_POST 数组中的只有:post
application/x-www-form-urlencode 不含有文件的表单性能
multipart/form-data 含有文件的表单(此时 php://input 和 $HTTP_RAW_POST_DATA 是没法识别数据流的)
两种php的标准数据类型
GET请求并不像POST请求会有 form body 数据,GET请求的全部信息都包含在了请求的header中 query string 中,经过url进行传递,说白了它所表明的是一个标识而不含有数据流,因此PHP并不会把 GET 请求装入数据流中,而只是简单的将其解析填充到$_GET数组当中
请求头:
GET url HTTP/1.1
Accept:期待服务器返回什么格式的数据 text/html application/json application/xml image/jpeg video/mp4 等等
POST请求包括header和from body,header头指明请求的url,form body 中存放数据提交给服务端,PHP 会根据提交的数据类型动态的将数据流转化为相应的模式,好比一下两种PHP能识别处理POST请求的数据类型
Content-Type:application/x-www-form-urlencoded //普通的表单 Content-Type:multipart/form-data //encrypt mutiple/form-data
=====================================================================
=====================================================================
其实你会发现普通的表单提交 from data 所携带的数据编码同 get 请求中的 query string 彻底同样,但这也是他们的本质区别, get 并不携带数据流 ,它彻底整合到 header 流中去,php 将其填充到 $_GET 数组中 , $_POST 数组中则是能被 PHP 识别并处理的 请求中的 from body (呃,就是 from data)中的数据
=====================================================================
=====================================================================
PHP能识别并处理的POST请求的数据类型只有
application/x-www-form-urlencode
multipart/form-data
注意是识别并处理,将 POST 过来的数据识别处理填充到全局 $_POST 数组中去,其余类型的数据则没法填充 $_POST 数组
但在工做中咱们不可能一直用表单请求服务器,APP开发时请求服务端每每发送的是 applicantion/json 或 applicant/xml 类型的参数数据,这时 PHP 没法识别处理此类数据流,但 PHP 会将此数据流存放在 php://input 数据流中
php://input 数据流存放的内容和 $HTTP_RAW_POST_DATA 的内容彻底同样 但牵扯到性能方面的问题咱们这里不推荐使用 $HTTP_RAW_POST_DATA 你能够认为 php://input 是一个资源
$input_stream = file_get_contents("php://input");
这样就获取到了此数据流中的内容
服务器端
<?php $input_stream =file_get_contents("php://input"); echo "==============this is php://input data===============\n"; echo $input_stream . "\n"; echo "==============this is post array data===============\n"; echo var_export($_POST, true); ?>
application/x-www-form-urlencoded post请求
curl -H "Content-Type:application/x-www-form-urlencoded" -X POST -d 'name=sallency&age=25' -o data.txt http://192.168.30.50:8082/curl.php //result ==============this is php://input data=============== name=sallency&age=25 ==============this is post data=================== array ( 'name' => 'sallency', 'age' => '25', )
application/json post请求
curl -H "Content-Type:application/json" -X POST --data '{"name":"sallency", "age":"25"}' -o data.txt http://192.168.30.50:8082/curl.php //result ==============this is php://input data=============== {"name":"sallency", "age":"25"} ==============this is post data=================== array ( )
application/xml post请求
curl -H "Content-Type:application/xml" -X POST -d '<?xml version="1.0" encoding="utf-8"?><user><name>sallency</name><age>25</age></user>' -o data.txt //result <?xml version="1.0" encoding="utf-8"?><user><name>sallency</name><age>25</age></user> ==============this is post data=================== array ( )
因为模拟mutipart/form-data的表单提交比较复杂咱们这里就不作模拟了
总结:
一、php 能识别处理的标准数据类型为:application/x-www-form-urlencoded(普通的表单) 和 mutipart/form-data(encrypt="mutipart/form-data" 的表单),其余的好比 application/json application/xml 是没有办法处理好填充到 $_POST 中去的,但它们会被填充到 php://input 流中(所谓处理是 php 自动解析好给你 拿来就用的意思 注意我文章中屡次提到识别和处理 )
二、php://input 能识别处理除 mutipart/form-data 外的全部类型的数据,将其填充到本身的数据流, 咱们能够经过它获取数据手动解析
=====================================================================
这些为数据流资源符
php://input php://output php://stdin php://stdout php://stderr
CLI下
STDIN = $stdin = fopen("php://stdin", "r") 是同样的 标准输入的句柄 STDOUT = $stdout = fopen("php://stdout", 'w') STDERR = $stderr = fopen("php://stderr", 'w')
fread(STDIN, 1024) fgets(STDIN) while ($line = fgets(STDIN)) { echo $line; } fwrite(STDOUT, "hello world!") file_get_contents("php://stdin") file_put_contents("php://stdout", "hello world!")
STDIN STDOUT STDERR 为句柄 能够直接被fread fwrite fgets使用 file_get_contents()/file_put_contents()打开或写入的是资源而不是资源句柄