CascadiaPHP 2024

stream_get_meta_data

(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)

stream_get_meta_dataヘッダーあるいはメタデータをストリームまたはファイルポインタから取得する

説明

stream_get_meta_data(resource $stream): array

既存の stream に関する情報を返します。

パラメータ

stream

ストリームは fopen()fsockopen()pfsockopen()stream_socket_client() で作成されたいずれのものも指定できます。

戻り値

結果の配列は次のような項目を含みます。

  • timed_out (bool) - 最後に fread() または fgets() でデータを待っている時にタイムアウトした場合 true を返します。

  • blocked (bool) - ストリームがブロック I/O モードの場合に true となります。 stream_set_blocking() を参照ください。

  • eof (bool) - ストリームが EOF に 達した時 true となります。 ストリームがソケットベースの場合、このメンバーは、 たとえ unread_bytes が 0 でなくても true になる場合があることに注意してください。 まだデータがあるかどうかを調べるには、このパラメータではなく、 feof() を使ってください。

  • unread_bytes (int) - PHP の 内部バッファにあるデータのバイト数。

    注意: スクリプト中でこの値を使用してはいけません。

  • stream_type (string) - ストリームの下層にある実装を表すラベル

  • wrapper_type (string) - ストリームを覆うプロトコルラッパーを表すラベル。 ラッパーについては サポートするプロトコル/ラッパー を参照ください。

  • wrapper_data (mixed) - ストリームに付随しているラッパーの固有のデータ。 ラッパーとその固有の情報については、サポートするプロトコル/ラッパー を参照ください。

  • mode (string) - このストリームに要求される アクセスモード(fopen() リファレンスの表 1 を参照ください)。

  • seekable (bool) - 現在のストリーム内で 移動が可能かどうか。

  • uri (string) - このストリームに関連付けられた URI / ファイル名。

  • crypto (array) - このストリームに関連付けられた TLS 接続のメタデータ (注意: リソースのストリームが TLS を使っている場合にのみ含まれます)

例1 fopen() を使い、http 経由で stream_get_meta_data() を使う例

<?php
$url
= 'http://www.example.com/';

if (!
$fp = fopen($url, 'r')) {
trigger_error("Unable to open URL ($url)", E_USER_ERROR);
}

$meta = stream_get_meta_data($fp);

var_dump($meta);

fclose($fp);
?>

上の例の出力は、 たとえば以下のようになります。

array(10) {
  'timed_out' =>
  bool(false)
  'blocked' =>
  bool(true)
  'eof' =>
  bool(false)
  'wrapper_data' =>
  array(13) {
    [0] =>
    string(15) "HTTP/1.1 200 OK"
    [1] =>
    string(11) "Age: 244629"
    [2] =>
    string(29) "Cache-Control: max-age=604800"
    [3] =>
    string(38) "Content-Type: text/html; charset=UTF-8"
    [4] =>
    string(35) "Date: Sat, 20 Nov 2021 18:17:57 GMT"
    [5] =>
    string(24) "Etag: "3147526947+ident""
    [6] =>
    string(38) "Expires: Sat, 27 Nov 2021 18:17:57 GMT"
    [7] =>
    string(44) "Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT"
    [8] =>
    string(22) "Server: ECS (chb/0286)"
    [9] =>
    string(21) "Vary: Accept-Encoding"
    [10] =>
    string(12) "X-Cache: HIT"
    [11] =>
    string(20) "Content-Length: 1256"
    [12] =>
    string(17) "Connection: close"
  }
  'wrapper_type' =>
  string(4) "http"
  'stream_type' =>
  string(14) "tcp_socket/ssl"
  'mode' =>
  string(1) "r"
  'unread_bytes' =>
  int(1256)
  'seekable' =>
  bool(false)
  'uri' =>
  string(23) "http://www.example.com/"
}

例2 stream_socket_client() を使い、https 経由で stream_get_meta_data() を使う例

<?php
$streamContext
= stream_context_create(
[
'ssl' => [
'capture_peer_cert' => true,
'capture_peer_cert_chain' => true,
'disable_compression' => true,
],
]
);

$client = stream_socket_client(
'ssl://www.example.com:443',
$errorNumber,
$errorDescription,
40,
STREAM_CLIENT_CONNECT,
$streamContext
);


$meta = stream_get_meta_data($client);

var_dump($meta);
?>

上の例の出力は、 たとえば以下のようになります。

array(8) {
  'crypto' =>
  array(4) {
    'protocol' =>
    string(7) "TLSv1.3"
    'cipher_name' =>
    string(22) "TLS_AES_256_GCM_SHA384"
    'cipher_bits' =>
    int(256)
    'cipher_version' =>
    string(7) "TLSv1.3"
  }
  'timed_out' =>
  bool(false)
  'blocked' =>
  bool(true)
  'eof' =>
  bool(false)
  'stream_type' =>
  string(14) "tcp_socket/ssl"
  'mode' =>
  string(2) "r+"
  'unread_bytes' =>
  int(0)
  'seekable' =>
  bool(false)
}

注意

注意:

この関数は、Socket 拡張モジュール で作成したソケットでは動作しません。

参考

add a note

User Contributed Notes 4 notes

up
10
php dot chaska at xoxy dot net
10 years ago
In PHP 5.4.24 and 5.4.25, this command does not correctly return the stream blocking status. It always returns ['blocked'] == 1 regardless of the actual blocking mode. A call to stream_set_blocking($stream, 0) will succeed (return TRUE) and subsequent calls to stream_get_contents($stream) will NOT block, even though a call to stream_get_meta_data($stream) will return 'blocked' == 1. Hopefully this will save some people a bunch of debugging time.

See bug report #47918 for more information (http://bugs.php.net/bug.php?id=47918).

Proof:
<?php
$d
= array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
2 => array('file', 'error.log', 'a')
);

$p = proc_open('php -S localhost:8000', $d, $pipes);

if (!
is_resource($p)) die("proc_open() failed\n");

// Set child's stdout pipe to non-blocking.
if (!stream_set_blocking($pipes[1], 0)) {
die(
"stream_set_blocking() failed\n");
}
else {
echo
"Non-blocking mode should be set.\n";
}

// View the status of that same pipe.
// Note that 'blocked' is 1! This appears to be wrong.
print_r(stream_get_meta_data($pipes[1]));

// Try to read something. This will block if in blocking mode.
// If it does not block, stream_set_blocking() worked but
// stream_get_meta_data() is lying about blocking mode.
$data = stream_get_contents($pipes[1]);

echo
"data = '$data'\n";
?>

Output:
Non-blocking mode should be set.
Array
(
[stream_type] => STDIO
[mode] => r
[unread_bytes] => 0
[seekable] =>
[timed_out] =>
[blocked] => 1 // << claims to be in blocking mode
[eof] =>
)
data = '' // this would never appear if we blocked.
up
5
ed at readinged dot com
21 years ago
Below is a function I wrote to pull the "Last-Modified" header from a given URL. In PHP version 4.3 and above, it takes advantage of the stream_get_meta_data function, and in older version it uses a conventional GET procedure. On failure to connect to $url, it returns NULL. If the server does not return the Last-Modified header, it returns the current time. All times are returned in PHP's integer format (seconds since epoch).

Use it as so:

$last_modified = stream_last_modified('http://www.php.net/news.rss');
if (!is_null($last_modified))
if ($last_modified < time()-3600) //Older than an hour
echo 'URL is older than an hour.';
else
echo 'URL is fairly new.';
else
echo 'Invalid URL!';

function stream_last_modified($url)
{
if (function_exists('version_compare') && version_compare(phpversion(), '4.3.0') > 0)
{
if (!($fp = @fopen($url, 'r')))
return NULL;

$meta = stream_get_meta_data($fp);
for ($j = 0; isset($meta['wrapper_data'][$j]); $j++)
{
if (strstr(strtolower($meta['wrapper_data'][$j]), 'last-modified'))
{
$modtime = substr($meta['wrapper_data'][$j], 15);
break;
}
}
fclose($fp);
}
else
{
$parts = parse_url($url);
$host = $parts['host'];
$path = $parts['path'];

if (!($fp = @fsockopen($host, 80)))
return NULL;

$req = "HEAD $path HTTP/1.0\r\nUser-Agent: PHP/".phpversion()."\r\nHost: $host:80\r\nAccept: */*\r\n\r\n";
fputs($fp, $req);

while (!feof($fp))
{
$str = fgets($fp, 4096);
if (strstr(strtolower($str), 'last-modified'))
{
$modtime = substr($str, 15);
break;
}
}
fclose($fp);
}
return isset($modtime) ? strtotime($modtime) : time();
}
up
-1
niels at nise81 dot com
16 years ago
here is just an example how to read out all meta data.
how ever I found out that the "seekable"-entry doesn't exist in most of the streaming media files.

if (!($fp = @fopen($url, 'r')))
return NULL;

$meta = stream_get_meta_data($fp);

foreach(array_keys($meta) as $h){
$v = $meta[$h];
echo "".$h.": ".$v."<br/>";
if(is_array($v)){
foreach(array_keys($v) as $hh){
$vv = $v[$hh];
echo "_".$hh.": ".$vv."<br/>";
}
}
}
fclose($fp);
up
-5
derkontrollfreak+9hy5l at gmail dot com
9 years ago
Apparently, custom wrappers are always seekable.
To Top