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

Параметр stream может быть любым потоком, созданным при помощи функций fopen(), fsockopen(), pfsockopen() и stream_socket_client().

Возвращаемые значения

Получаемый массив содержит следующие элементы:

  • timed_out (bool) - true, если поток превысил время ожидания данных во время последнего вызова функции fread() или fgets().

  • blocked (bool) - true, если поток находится в режиме блокирующего ввода-вывода. Смотрите функцию stream_set_blocking().

  • eof (bool) - true, если поток достиг конца файла. Заметьте, что для потоков типа socket этот член может быть равен true, даже когда unread_bytes не равно нулю. Для того, чтобы определить есть ли ещё данные для чтения, используйте feof() вместо чтения этого элемента.

  • unread_bytes (int) - количество байт, находящихся сейчас в собственном внутреннем буфере PHP.

    Замечание: Вы не должны использовать это значение в скрипте.

  • stream_type (string) - метка, описывающая внутреннюю реализацию потока.

  • wrapper_type (string) - метка, описывающая реализацию обёртки протокола, наложенного на поток. Смотрите раздел Поддерживаемые протоколы и обёртки для подробной информации об обёртках.

  • wrapper_data (mixed) - специфические для обёртки данные, прикреплённые к этому потоку. Смотрите раздел Поддерживаемые протоколы и обёртки для подробной информации об обёртках и их данных.

  • mode (string) - тип доступа, требуемый для этого потока (смотрите таблицу 1 в описании функции fopen())

  • seekable (bool) - можно ли перемещаться по текущему потоку.

  • uri (string) - URI/имя файла, связанное с этим потоком.

  • crypto (array) - метаданные TLS-соединения потока. Примечание: указывается только в том случае, если поток ресурса использует TLS.

Примеры

Пример #1 Пример использования stream_get_meta_data() с использованием fopen() с http

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

if (!
$fp = fopen($url, 'r')) {
trigger_error("Невозможно открыть 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_get_meta_data() с использованием stream_socket_client() с https

<?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 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
10 years ago
Apparently, custom wrappers are always seekable.
To Top