Please note that the callback function never gets called when the stream is (at least) of type socket. It is probably the same for the file:// proto although I've not done further tests.
I'm using php 5.3.3.
(PHP 5 >= 5.2.0, PHP 7, PHP 8)
stream_notification_callback — notification
bağlam bağımsız değişkeni için bir
geri çağırım işlevi
$bildirim_kodu
,$önem
,$ileti
,$ileti_kodu
,$bayt_sayısı
,$azami_bayt_sayısı
Bir olay sırasında çağrılmak üzere notification
bağlam bağımsız değişkeni tarafından
kullanılan bir geriçağırım işlevi.
Bilginize:
Bu gerçek bir işlev olmayıp, kullanacağınız işlevin bir örneği olarak tasarlanmıştır.
bildirim_kodu
STREAM_NOTIFY_*
bildirim sabitlerinden biri.
önem
STREAM_NOTIFY_SEVERITY_*
bildirim sabitlerinden biri.
ileti
Olayı açıklayan bir ileti.
ileti_kodu
Olay için kullanılabilecek açıklayıcı bir ileti kodu.
Bu değerin anlamı kullanılacak sarmalayıcıya bağlıdır.
bayt_sayısı
Uygulanabilirse, aktarılacak baytların sayısı.
azami_bayt_sayısı
Uygulanabilirse, aktarılacak baytların azami sayısı.
Hiçbir değer dönmez.
Örnek 1 - stream_notification_callback() örneği
<?php
function stream_notification_callback($bildirim_kodu, $önem, $ileti,
$ileti_kodu, $bayt_sayısı, $azami_bayt_sayısı) {
switch($bildirim_kodu) {
case STREAM_NOTIFY_RESOLVE:
case STREAM_NOTIFY_AUTH_REQUIRED:
case STREAM_NOTIFY_COMPLETED:
case STREAM_NOTIFY_FAILURE:
case STREAM_NOTIFY_AUTH_RESULT:
var_dump($bildirim_kodu, $önem, $ileti, $ileti_kodu,
$bayt_sayısı, $azami_bayt_sayısı);
/* yoksay */
break;
case STREAM_NOTIFY_REDIRECTED:
echo "Yönlendirildiği yer: ", $ileti;
break;
case STREAM_NOTIFY_CONNECT:
echo "Bağlandı...";
break;
case STREAM_NOTIFY_FILE_SIZE_IS:
echo "Alınan dosya boyu: ", $azami_bayt_sayısı;
break;
case STREAM_NOTIFY_MIME_TYPE_IS:
echo "Bulunan MIME türü: ", $ileti;
break;
case STREAM_NOTIFY_PROGRESS:
echo "Biraz işlem yapılıp, ", $bayt_sayısı, " bayt indirildi";
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);
?>
Yukarıdaki örnek şuna benzer bir çıktı üretir:
Bağlandı... Bulunan MIME türü: text/html; charset=utf-8 Yönlendirildiği yer: http://no.php.net/contact Bağlandı... Alınan dosya boyu: 0 Bulunan MIME türü: text/html; charset=utf-8 Yönlendirildiği yer: http://no.php.net/contact.php Bağlandı... Alınan dosya boyu: 4589 Bulunan MIME türü: text/html;charset=utf-8 Biraz işlem yapılıp, 0 bayt indirildi Biraz işlem yapılıp, 0 bayt indirildi Biraz işlem yapılıp, 0 bayt indirildi Biraz işlem yapılıp, 1440 bayt indirildi Biraz işlem yapılıp, 2880 bayt indirildi Biraz işlem yapılıp, 4320 bayt indirildi Biraz işlem yapılıp, 5760 bayt indirildi Biraz işlem yapılıp, 6381 bayt indirildi Biraz işlem yapılıp, 7002 bayt indirildi
Örnek 2 - Komut satırı istemcisi için basit bir ilerleme çubuğu
<?php
function usage($argv) {
echo Kullanım:\n";
printf("\tphp %s <http://example.com/file> <yereldosya>\n", $argv[0]);
exit(1);
}
function stream_notification_callback($bildirim_kodu, $önem, $ileti,
$ileti_kodu, $bayt_sayısı, $azami_bayt_sayısı) {
static $dosyaboyu = null;
switch($bildirim_kodu) {
case STREAM_NOTIFY_RESOLVE:
case STREAM_NOTIFY_AUTH_REQUIRED:
case STREAM_NOTIFY_COMPLETED:
case STREAM_NOTIFY_FAILURE:
case STREAM_NOTIFY_AUTH_RESULT:
/* yoksay */
break;
case STREAM_NOTIFY_REDIRECTED:
echo "Yönlendirildiği yer: ", $ileti, "\n";
break;
case STREAM_NOTIFY_CONNECT:
echo "Bağlandı...\n";
break;
case STREAM_NOTIFY_FILE_SIZE_IS:
$dosyaboyu = $azami_bayt_sayısı;
echo "Dosya uzunluğu: ", $dosyaboyu, "\n";
break;
case STREAM_NOTIFY_MIME_TYPE_IS:
echo "MIME türü: ", $ileti, "\n";
break;
case STREAM_NOTIFY_PROGRESS:
if ($bayt_sayısı > 0) {
if (!isset($dosyaboyu)) {
printf("\rDosya uzunluğu bilinmiyor... %2d kb alındı..",
$bayt_sayısı/1024);
} else {
$length = (int)(($bayt_sayısı/$dosyaboyu)*100);
printf("\r[%-100s] %%%d (%2d/%2d kb)", str_repeat("=",
$length). ">", $length, ($bayt_sayısı/1024), $dosyaboyu/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 "\nBitti!\n";
exit(0);
}
$err = error_get_last();
echo "\nHataaaa..\n", $err["message"], "\n";
exit(1);
?>
Yukarıdaki örneği şu komutla çalıştıralım:
php -n fetch.php
http://no2.php.net/get/php-5-LATEST.tar.bz2/from/this/mirror
php-latest.tar.bz2
. Çıktı şöyle olacaktır:
Bağlandı... MIME türü: text/html; charset=utf-8 Yönlendirildiği yer: http://no2.php.net/distributions/php-5.2.5.tar.bz2 Bağlandı... Dosya uzunluğu: 7773024 MIME türü: application/octet-stream [===============> ] %40 (3076/7590 kb)
Please note that the callback function never gets called when the stream is (at least) of type socket. It is probably the same for the file:// proto although I've not done further tests.
I'm using php 5.3.3.
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;
}
}
?>
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";
?>