PHP 8.5.0 Alpha 1 available for testing

stream_notification_callback

(PHP 5 >= 5.2.0, PHP 7, PHP 8)

stream_notification_callbackUna función de retrollamada para el parámetro de contexto notification

Descripción

stream_notification_callback(
    int $notification_code,
    int $severity,
    ?string $message,
    int $message_code,
    int $bytes_transferred,
    int $bytes_max
): void

Una función de retrollamada de tipo callable, utilizada por el parámetro de contexto notification, llamada durante un evento.

Nota:

Esto no es una función real, únicamente un prototipo de cómo debe ser la función.

Parámetros

notification_code

Una de las constantes de notificación STREAM_NOTIFY_*.

severity

Una de las constantes de notificación STREAM_NOTIFY_SEVERITY_*.

message

Pasado si un mensaje descriptivo está disponible para este evento.

message_code

Pasado si un código de mensaje descriptivo está disponible para este evento.

El significado de este valor depende del gestor específico utilizado.

bytes_transferred

Si es posible, bytes_transferred será rellenado.

bytes_max

Si es posible, bytes_max será rellenado.

Valores devueltos

No devuelve ningún valor.

Historial de cambios

Versión Descripción
8.3.0 Soporte para STREAM_NOTIFY_COMPLETED implementado, las versiones anteriores de PHP nunca desencadenaban esta notificación.

Ejemplos

Ejemplo #1 Ejemplo con stream_notification_callback()

<?php
function stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {

switch(
$notification_code) {
case
STREAM_NOTIFY_RESOLVE:
case
STREAM_NOTIFY_AUTH_REQUIRED:
case
STREAM_NOTIFY_COMPLETED:
case
STREAM_NOTIFY_FAILURE:
case
STREAM_NOTIFY_AUTH_RESULT:
var_dump($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max);
/* Ignorar */
break;

case
STREAM_NOTIFY_REDIRECTED:
echo
"Redirección a: ", $message;
break;

case
STREAM_NOTIFY_CONNECT:
echo
"Conectado...";
break;

case
STREAM_NOTIFY_FILE_SIZE_IS:
echo
"Obteniendo el tamaño del fichero: ", $bytes_max;
break;

case
STREAM_NOTIFY_MIME_TYPE_IS:
echo
"Tipo mime encontrado: ", $message;
break;

case
STREAM_NOTIFY_PROGRESS:
echo
"Descargando, ya ", $bytes_transferred, " bytes transferidos";
break;
}
echo
"\n";
}

$ctx = stream_context_create();
stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));

file_get_contents("http://php.net/contact", false, $ctx);
?>

El resultado del ejemplo sería algo similar a:

Conectado...
Tipo mime encontrado: text/html; charset=utf-8
Redirección a: http://no.php.net/contact
Conectado...
Obteniendo el tamaño del fichero: 0
Tipo mime encontrado: text/html; charset=utf-8
Redirección a: http://no.php.net/contact.php
Conectado...
Obteniendo el tamaño del fichero: 4589
Tipo mime encontrado: text/html;charset=utf-8
Descargando, ya 0 bytes transferidos
Descargando, ya 0 bytes transferidos
Descargando, ya 0 bytes transferidos
Descargando, ya 1440 bytes transferidos
Descargando, ya 2880 bytes transferidos
Descargando, ya 4320 bytes transferidos
Descargando, ya 5760 bytes transferidos
Descargando, ya 6381 bytes transferidos
Descargando, ya 7002 bytes transferidos

Ejemplo #2 Barra de progreso simple para un cliente de descarga en línea de comandos

<?php
function usage($argv) {
echo
"Uso:\n";
printf("\tphp %s <http://example.com/file> <localfile>\n", $argv[0]);
exit(
1);
}

function
stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
static
$filesize = null;

switch(
$notification_code) {
case
STREAM_NOTIFY_RESOLVE:
case
STREAM_NOTIFY_AUTH_REQUIRED:
case
STREAM_NOTIFY_COMPLETED:
case
STREAM_NOTIFY_FAILURE:
case
STREAM_NOTIFY_AUTH_RESULT:
/* Ignorar */
break;

case
STREAM_NOTIFY_REDIRECTED:
echo
"Redirección a: ", $message, "\n";
break;

case
STREAM_NOTIFY_CONNECT:
echo
"Conectado...\n";
break;

case
STREAM_NOTIFY_FILE_SIZE_IS:
$filesize = $bytes_max;
echo
"Tamaño del fichero: ", $filesize, "\n";
break;

case
STREAM_NOTIFY_MIME_TYPE_IS:
echo
"Tipo Mime: ", $message, "\n";
break;

case
STREAM_NOTIFY_PROGRESS:
if (
$bytes_transferred > 0) {
if (!isset(
$filesize)) {
printf("\rTamaño del fichero desconocido.. %2d kb hechos..", $bytes_transferred/1024);
} else {
$length = (int) (($bytes_transferred/$filesize)*100);
printf("\r[%-100s] %d%% (%2d/%2d kb)", str_repeat("=", $length). ">", $length, ($bytes_transferred/1024), $filesize/1024);
}
}
break;
}
}

isset(
$argv[1], $argv[2]) or usage($argv);

$ctx = stream_context_create();
stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));

$fp = fopen($argv[1], "r", false, $ctx);
if (
is_resource($fp) && file_put_contents($argv[2], $fp)) {
echo
"\n¡Hecho!\n";
exit(
0);
}

$err = error_get_last();
echo
"\n¡Error!\n", $err["message"], "\n";
exit(
1);
?>

Ejecute el ejemplo anterior con: php -n fetch.php http://no2.php.net/get/php-5-LATEST.tar.bz2/from/this/mirror php-latest.tar.bz2 mostrará algo similar a:

Conectado...
Tipo Mime: text/html; charset=utf-8
Redirección a: http://no2.php.net/distributions/php-5.2.5.tar.bz2
Conectado...
Tamaño del fichero: 7773024
Tipo Mime: application/octet-stream
[========================================>                                                           ] 40% (3076/7590 kb)

Ver también

add a note

User Contributed Notes 2 notes

up
3
billynoah at gmail dot com
8 years ago
A couple of notes regarding the examples here (I'm using PHP 7.0.18):

1) fopen() did not provide STREAM_NOTIFY_PROGRESS for me but `file_get_contents()` worked fine.

2) The bytes transferred when transferring a zip file seems to always be shy by 8192 (8k). This varies depending on filetype and also breaks STREAM_NOTIFY_PROGRESS when the filesize is below 8k. I modified the function and it's now displaying the correct amount transferred and percentage downloaded on zip files above 8k. I'm not sure why the callback is so inconsistent but hopefully this is helpful to someone. This was also modified to only display progress:

<?php

$ctx
= stream_context_create();
stream_context_set_params($ctx, array("notification" => "stream_notification_callback"));
$fileData = @file_get_contents('http://example.com/test.zip',false,$ctx);

function
stream_notification_callback($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
static
$filesize = null;
switch(
$notification_code) {
case
STREAM_NOTIFY_FILE_SIZE_IS:
$filesize = $bytes_max;
break;
case
STREAM_NOTIFY_CONNECT:
echo
"Connected...\n";
break;
case
STREAM_NOTIFY_PROGRESS:
if (
$bytes_transferred > 0 && $filesize >= 8192) {
$bytes_transferred += 8192;
if (!isset(
$filesize)) {
printf("\rUnknown filesize.. %2d kb done..", $bytes_transferred/1024);
} else {
$length = (int)(($bytes_transferred/$filesize)*100);
printf("\r[%-100s] %d%% (%2d/%2d kb)", str_repeat("=", $length). ">", $length, ($bytes_transferred/1024), $filesize/1024);
}
}
break;
}
}
?>
up
2
aetonsi
2 years ago
A couple of unreported behaviors:
- case 1) if this callback calls die/exit($msg), it will print $msg, then the execution will go on until the request/wrapper is consumed, emitting a "PHP Warning: Failed to call user notifier" on each invocation of the callback. After the last callback invocation, the script is immediately terminated.
- case 2) if this callback throws an exception, it will behave the same way as exit/die, except for the fact that after the last callback invocation it does not terminate the script. The exception is instead raised in the scope of the request/wrapper, and can be caught with a try catch (right there or at a higher level).

Example code for case 1). The final "TEST ECHO" string will NOT be printed.
<?php
$context
= stream_context_create(['http' => ['ignore_errors' => true,]]);
stream_context_set_params($context, ['notification' => function () {
die(
'error');
}]);

file_get_contents('https://www.google.com', false, $context);
echo
"TEST ECHO";
?>

Example code for case 2). The exception is raised at the level of the file_get_contents call, it's catched, and the final "TEST ECHO" gets printed.
<?php
$context
= stream_context_create(['http' => ['ignore_errors' => true,]]);
stream_context_set_params($context, ['notification' => function () {
throw new
Exception('...');
}]);

try{
file_get_contents('https://www.google.com', false, $context);
}catch(
exception $e) { }
echo
"TEST ECHO";
?>
To Top