支持的协议和包装器

PHP 带有许多内置包装器,用于各种 URL 风格的协议,与文件系统函数(如 fopen()copy()file_exists()filesize())一起使用。除了这些包装器,还可以使用 stream_wrapper_register() 函数注册自定义包装器。

注意: 用于描述包装器的 URL 语法仅支持 scheme://... 语法。不支持 scheme:/scheme: 语法。

目录

添加备注

用户贡献的备注 31 个备注

24
fabacrans__ at __nospamhotmail__ dot __com
11 年前
您可以使用 "php://input" 来接受和解析 "PUT"、"DELETE" 等请求。

<?php
// 解析 "PUT" 请求的示例
parse_str(file_get_contents('php://input'), $_PUT);

// 结果
print_r($_PUT);
?>

(非常适合 Restful API)
17
ben dot johansen at gmail dot com
17 年前
如何使用 php://input 获取原始 POST 数据的示例

// 读取原始数据
$roughHTTPPOST = file_get_contents("php://input");
// 解析为变量
parse_str($roughHTTPPOST);

如果您执行 readfile("php://input"),您将获得 POST 数据的长度
13
aidan at php dot net
20 年前
常量

* STDIN
* STDOUT
* STDERR

在 PHP 4.3.0 中引入,与 fopen('php://stdx') 结果资源相同。
18
sander at medicore dot nl
17 年前
要创建一个原始 TCP 监听器系统,我使用以下方法

xinetd 守护程序,配置如下
service test
{
disable = no
type = UNLISTED
socket_type = stream
protocol = tcp
bind = 127.0.0.1
port = 12345
wait = no
user = apache
group = apache
instances = 10
server = /usr/local/bin/php
server_args = -n [您的 PHP 文件在这里]
only_from = 127.0.0.1 # 要爱上安全性 #
log_type = FILE /var/log/phperrors.log
log_on_success += DURATION
}

现在使用 fgets(STDIN) 读取输入。创建连接速度非常快,效果很好。写入可以使用 STDOUT 完成,或者直接使用 echo。请注意,您完全绕过了 Web 服务器,因此某些变量将不可用。
13
ben dot johansen at gmail dot com
17 年前
在尝试使用 PHP 和 Javascript 进行 AJAX 时,我遇到了一个问题,使用 $_REQUEST 或 $_POST 在 PHP 5 中无法读取以下 Javascript 中的 POST 参数。我终于找到了如何使用 php://input 指令读取原始数据。

Javascript 代码
=============
// 创建请求实例
xhttp = new XMLHttpRequest();
// 设置事件处理程序
xhttp.onreadystatechange = serviceReturn;
// 准备调用,http 方法=POST,true=异步调用
var Args = 'number='+NbrValue;
xhttp.open("POST", "http://<?php echo $_SERVER['SERVER_NAME'] ?>/webservices/ws_service.php", true);
// 使用参数发送调用
xhttp.send(Args);

PHP 代码
// 读取原始数据
$roughHTTPPOST = file_get_contents("php://input");
// 解析为变量
parse_str($roughHTTPPOST);
11
php at rapsys dot eu
12 年前
以下是一段代码,用于在不启用全局变量的情况下读取压缩的原始 POST 数据。

我需要它来读取由 ocs 代理提交的 POST 的 XML 数据。数据以 Content-Type: application/x-compressed(zlib 压缩数据)发送。

它似乎与一个旧的错误有关,该错误似乎仍然存在
https://bugs.php.net/bug.php?id=49411

重要的是将默认窗口设置为 15 而不是 -15。

代码片段
<?php
$data
= '';
$fh = fopen('php://input', 'rb');
stream_filter_append($fh, 'zlib.inflate', STREAM_FILTER_READ, array('window'=>15));
while(!
feof($fh)) {
$data .= fread($fh, 8192);
}
?>
10
sebastian dot krebs at kingcrunch dot de
13 年前
流 php://temp/maxmemory:$limit 将数据存储在内存中,除非达到限制。然后它会将整个内容写入临时文件并释放内存。我找不到将至少部分数据返回到内存的方法。
12
Hayley Watson
6 年前
即使它们的名称相同,您也可以同时打开多个 //memory 或 //temp 流;每次您 fopen() 这样的流时,都会打开一个新的流,与其他流无关。

这暗示了您在创建此类流时没有在路径中添加任何唯一标识符,但没有明确说明。

<?php

$hello
= fopen('php://memory', 'r+'); // $hello、$php、$world 都是不同的流。
$php = fopen('php://memory', 'r+');
$world = fopen('php://memory', 'r+'); // 它们不是同一个流打开了三次。

fputs($hello, "Hello ");
fputs($php, "PHP ");
rewind($php);
fputs($world, "World!");
rewind($hello);
rewind($world);

echo
'[', stream_get_contents($hello), '][', stream_get_contents($php), '][', stream_get_contents($world), ']';
// 如果它们是同一个流,输出将为 "[World!][World!][World!]".
?>
12
gjaman at gmail dot com
16 年前
您可以通过组合包装器来解压缩(gzip)输入流

例如:$x = file_get_contents("compress.zlib://php://input");

我使用这种方法来解压缩推送到我的 Web 服务器的 gzip 流
9
heitorsiller at uol dot com dot br
18 年前
要读取 XML 流,这就可以了
<?php

$arq
= file_get_contents('php://input');

?>

然后你可以像这样解析 XML

<?php

$xml
= xml_parser_create();

xml_parse_into_struct($xml, $arq, $vs);

xml_parser_free($xml);

$data = "";

foreach(
$vs as $v){

if(
$v['level'] == 3 && $v['type'] == 'complete')
$data .= "\n".$v['tag']." -> ".$v['value'];
}

echo
$data;

?>

PS:这对于接收来自手机公司的移动源(MO)短信特别有用。
8
nargy at yahoo dot com
19 年前
以追加模式打开 php://output 时,会出错,解决方法如下
$fp=fopen("php://output","w");
fwrite($fp,"Hello, world !<BR>\n");
fclose($fp);
6
vibhavsinha91 at gmail dot com
9 年前
写入错误流时,error_log() 函数是写入 php://stderr 的简写。这个函数还允许在通过像 apache 这样的 Web 服务器运行时写入 Web 服务器日志。
4
匿名
6 年前
注意

file_get_contents 中使用的 file:// 协议用作“任何无法识别的协议”的默认值。因此

aldfjadlfadfladfl://whatever

将与

file://whatever
7
匿名
7 年前
如果你想通过 php://input 过滤传入数据,可以使用这个

file_get_contents("php://filter/read=string.strip_tags/resource=php://input");

我找不到任何文档解释如何做到这一点。我遇到的所有示例都建议必须使用完整的实际 URL(这对我不起作用)。

这似乎有效。
6
Justin Megawarne
11 年前
如果我对实现代码的理解正确,每次打开 php://memory 流时,都会获得新的存储分配。也就是说,php://memory 不是共享内存库。
7
sam at bigwig dot net
20 年前
[ 编辑注:有一种方法可以知道。所有响应头(来自最终响应服务器和中间重定向器)都可以在 $http_response_header 或 stream_get_meta_data() 中找到,如上所述。 ]

如果你打开一个 HTTP URL,并且服务器发出 Location 风格的重定向,重定向的内容将被读取,但你无法发现发生了这种情况。

因此,如果你随后解析返回的 html 并尝试合理化相对 URL,你可能会出错。
5
chris at free-source dot com
19 年前
如果你正在寻找基于 Unix 的 smb 包装器,则没有内置的包装器,但我对 http://www.zevils.com/cgi-bin/viewcvs.cgi/libsmbclient-php/(末尾的 tarball 链接)很满意。
5
jerry at gii dot co dot jp
16 年前
STDIN、STDOUT 和 STDERR 不仅限于 CLI 程序,而且不允许用于从 STDIN 读取的程序。如果你尝试输入一个简单的测试程序,这可能会让你困惑。
5
lupti at yahoo dot com
20 年前
我发现使用 file_get_contents 与 php://input 非常方便且高效。以下是代码

$request = "";
$request = file_get_contents("php://input");

我不需要将 URL 文件字符串声明为“r”。它会自动处理以读取方式打开文件。

然后我可以用这个 $request 字符串作为数据来使用你的 XMLparser。
5
aaron dot mason+php at thats-too-much dot info
12 年前
注意代码注入,伙计们 - 就像你从用户那里获取的任何其他东西一样,首先进行清理。这一点再怎么强调也不为过 - 如果我有一美元就能得到每次看到代码的地方,这些代码直接使用表单输入(我自己也是,我也很蠢),我可能会拥有 PHP。虽然在 URL 包装器中使用来自表单的数据是在自找麻烦,但你可以通过确保输入是合理的,并且不太可能为世界 LulzSec 提供造成混乱的机会来最大限度地减少麻烦。
5
leonid at shagabutdinov dot com
13 年前
对于 Windows 上的 https,启用此扩展

extension=php_openssl.dll
4
nyvsld at gmail dot com
18 年前
php://stdin 支持 fseek() 和 fstat() 函数调用,
而 php://input 则不支持。
4
ben dot johansen at gmail dot com
17 年前
后续

我发现如果我在 AJAX 调用中添加这行代码,这些值就会显示在 $_POST 中

xhttp.setRequestHeader('Content-Type',
'application/x-www-form-urlencoded');
1
kazdotkanso at geeemail dot com
3 年前
php://fd/ 包装器仅在 cli 工具中受支持。
3
oliver at codeinline dot com
10 年前
处理大型文件上传的一个有用方法是执行以下操作

copy(("php://input"),$tmpfile);

因为这避免了仅仅为了缓冲文件内容而使用大量内存。

这的正确 mime 类型应该是“application/octet-stream”,但是如果你在 POST 上设置了这个或任何其他识别的 mime 类型(除了“multipart/form-data”),则会填充 $HTTP_RAW_POST_DATA,并且内存也会被消耗。

将 mime 类型设置为“multipart/form-data”会导致“PHP Warning: Missing boundary in multipart/form-data POST data in Unknown on line 0”,但是它似乎在没有问题的情况下工作。
3
匿名
12 年前
对于 php://filter,/resource=foo 部分必须放在最后。并且 foo 完全不需要转义。
php://filter/resource=foo/read=somefilter 会尝试打开文件“foo/read=somefilter”,而 php://filter/read=somefilter/resource=foo 会打开文件“foo”,并应用 somefilter 过滤器。
3
dave at 4mation dot com dot au
11 年前
将 php://temp/maxmemory 用作流会计算在脚本的内存使用量中;你没有通过使用这种类型的流来指定新的内存池。
如文档中所述,但是,当超过指定的 maxmemory 限制后,此流类型将开始写入文件。此文件缓冲区不受内存限制的观察。
如果你希望你的脚本具有合理的内存限制(例如 32MB),但仍然能够处理大量流数据(例如 256MB),这将非常方便。

这仅在使用 fputs() 等流函数时才有效;如果你使用 $buffer .= 'string' 或 $buffer = $buffer . 'string',你将调用流数据返回到 PHP,这将击中限制器。

作为一个实际的例子

<?php
// 0.5MB 内存限制
ini_set('memory_limit', '0.5M');
// 2MB 流限制
$buffer = fopen('php://temp/maxmemory:1048576', 'r+');
$x = 0;
// 尝试将 1MB 写入流
while ($x < 1*1024*1024) {
fputs($buffer, 'a');
$x++;
}
echo
"这将永远不会显示";
?>

但是,将 fopen 更改为使用 php://temp/maxmemory:1(一个字节,而不是一个兆字节),它会立即开始写入无限制的文件流,避免内存限制错误。
1
匿名
8 年前
请注意,STDIN 及类似的只有在 CLI 中定义。
1
ohcc at 163 dot com
8 年前
<?php
// 在需要时启用 $HTTP_RAW_POST_DATA
ini_set('always_populate_raw_post_data',-1);
$HTTP_RAW_POST_DATA = file_get_contents('php://input');
echo
$HTTP_RAW_POST_DATA;
?>
1
匿名
11 年前
在 PHP 5.4+ 中,如果你将 enable_post_data_reading 设置为 Off,则可以通过 php://input 读取 multipart 数据。

当然,如果你将其设置为 off,则 $_POST 和 $_FILES 超级全局变量将根本不会填充。现在完全由你解析数据。
-2
nguyenanthuan at gmail dot com
9 年前
指向 php://memory 和 php://temp 的每个流指针都有其自己的内存分配,因此你可以打开多个流指针来存储你的分离值。

<?php
$fp
= fopen("php://temp", "r+");
$fp2 = fopen("php://temp", "r+");

fwrite($fp, "line1\n");
fwrite($fp2, "line4\n");
fwrite($fp, "line2\n");
fwrite($fp2, "line5\n");
fwrite($fp, "line3\n");
fwrite($fp2, "line6\n");

var_dump(memory_get_usage());

rewind($fp);
while(!
feof($fp)) {
var_dump(fread($fp, 1024));
}
fclose($fp);
var_dump(memory_get_usage());

rewind($fp2);
while(!
feof($fp2)) {
var_dump(fread($fp2, 1024));
}
fclose($fp2);
var_dump(memory_get_usage());
?>

关闭它们的流句柄也将释放已分配的内存。

php://memory 流类型是 MEMORY,而 php://temp 流类型是 STDIO FILE*。
To Top