Только для читателей Lifeexample возможно открыть интернет-магазин на Moguta.CMS со скидкой в 15%
Php+Ajax полоса загрузки ProgressBar
Здравствуй уважаемый читатель блога LifeExample, ты знаешь, что такое ProgressBar? ProgressBar — это индикатор, который показывает скорость и процент выполнения любого процесса. ProgressBar также называют полосой загрузки, или индикатором загрузки. Обычно прогресс бар используют для отображения процесса скачивания или закачивания файлов, но существуют и другие способы применения. Почему то в интернете все ссылки связанные использованием ProgressBar на php, сводятся к загрузке файлов, неужели людям не нужно отслеживать процесс выполнения других задач? Например, таких как процент считывания XML файла, или процесс заполнения SQL таблицы данными. Немало важным индикатор отслеживания является и при работе с удаленным сервером.
Недавно мне пришлось разработать грабер для одной фирмы. Грабер должен был: получить с сайта конкурентов, каталог продукции, сохранив структуру вложенности разделов. Так вот при частом обращении с чужому серверу, с целью получения кода страницы, для дальнейшего парсинга, уходит много времени, что влечет за собой появление ошибки выполнения сценария:
Fatal error: Maximum execution time of 30 seconds exceeded in …
Для того чтобы избежать данной оказии, нужно разбить наш процесс на части, таким образом чтобы каждая из частей при выполнении укладывалась в 30 секундный интервал. В этот момент как раз таки и неплохо знать, сколько же процентов выполнилось, и сколько еще осталось ждать.
Пишем PHP скрипт для полосы загрузки с использованием AJAX
Представим, что у нас есть объемный алгоритм, который обрабатывает информацию по частям, и назовем его условно «сложной задачей». Чтобы было понятно, представьте что информацией является разбитый на части файл, который нужно скачать с сервера.
Создавать ProgressBar мы будем последовательно, выполнив для этого 3 шага.
AJAX обработчик (Шаг 1)
Сразу скажу, что для корректной работы AJAX технологии нам понадобится, уже готовый скрипт:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | function XmlHttp() { var xmlhttp; try{xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");} catch(e) { try {xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");} catch (E) {xmlhttp = false;} } if (!xmlhttp && typeof XMLHttpRequest!='undefined') { xmlhttp = new XMLHttpRequest(); } return xmlhttp; } function ajax(param) { if (window.XMLHttpRequest) req = new XmlHttp(); send=""; for (var i in param.data) send+= i+"="+param.data[i]+"&"; req.open("POST", param.url, true); req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); req.send(send); req.onreadystatechange = function() { if (req.readyState == 4 && req.status == 200) //если ответ положительный { if(param.success)param.success(req.responseText); } } } |
И так, скачайте данный скрипт, и положите его в корневую папку вашего сайта, либо в ручную создайте пустой файл ajax.js и вставьте в него приведенный выше код.
Пишем скрипт PHP выполняющий «сложную задачу» (Шаг 2)
Вторым действием создадим скрипт index.php , который будет отвечать за вывод полосы загрузки на страницу, а также будет выполнять расчет «сложной задачи». В корневой папке сайта создайте пустой файл index.phр. Откройте его и вставьте следующий код:
1 2 3 4 5 6 7 8 9 10 11 | <? session_start();//открываем сессию для записи if($_POST["difficult_task"]){ $part=231; //общее количество задач $_SESSION['sucsess_part']++; //количество выполненных подзадач echo floor(($_SESSION['sucsess_part']*100)/$part);//процент выполненния общей задачи } ?> else{?> … <?}?> |
Эта часть кода описывает процесс выполнения «сложной задачи», если интерпретировать ее на задачу скачивания файла, то переменная $part должна содержать количество частей разбитого файла. Счетчик уже скачанных частей должен храниться в сессии на сервере, поэтому сразу открываем ее для записи функцией session_start(), для того чтобы в дальнейшем увеличивать $_SESSION[‘sucsess_part’] на один, каждый раз при успешной закачке одной из частей файла. Функция floor() округляет выполненные проценты скачивания до целого числа в меньшую сторону.
Вот и весь скрипт расчета сложной задачи, конечно на практике данный скрипт разрастётся сотнями строк, но для общего примера хватит и данного кода. В принципе правильнее было бы выделить этот скрипт отдельно и обращаться к нему с html странички с помощью ajax.js, но т.к. он слишком мал, то будет понятнее включить обработчик «сложной задачи» непосредственно в код страницы.
Организация процесса обновления полосы загрузки и вывод её на страницу (3 шаг)
Код вывода HTML страницы и progressbar будет заключен между скобками else из предыдущего шага:
1 2 3 | else{?> … <?}?> |
Скопируйте следующий кусок кода и вставьте его вместо многоточия.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | <html> <head> <title>Сложная задача</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <script type="text/javascript" src="ajax.js"></script> <script> function ProgressBar(persent){ if(persent<100){ //если задача не достигла 100% готовности, отправляем запрос на ее выполнение ajax({ url:"http://<?=$_SERVER['HTTP_HOST']."/progressbar/index.php";?>", //путь к скрипту, который обрабатывает задачу data: //данные передаваемые в POST запросе { difficult_task:"difficult_task", }, success:function(data){ //функция обратного вызова, выполняется в случае успехной отработки скрипта document.getElementById("text").innerHTML="<br/>Завершено <b>"+data+"%</b>"; // выводим в информационный блок количество выполненных % document.getElementById("bar").style.width=data+"%"; //растягиваем полосу загрузки document.getElementById("persent").innerHTML=data+"%"; // изменяем счетчик процентов, на полосе загрузки ProgressBar(parseInt(data));// рекурсивно вызываем этуже функцию, она будет выполняться пока не выполнит 100% } }) } else{//если задача выполненна на 100%, то выводим информацию об этом. document.getElementById("status").innerHTML=""; document.getElementById("text").innerHTML="<br/> Задача успешно выполнена!<br/>Для повторного запуска нужно сбросить сессию. (Перезапустите браузер)"; document.getElementById("bar").style.width="0%"; document.getElementById("load").style.display="none"; document.getElementById("bar").style.display="none"; document.getElementById("btn").style.display="none"; } } </script> </head> <body> <form method="post" action=""> <div id="status"></div> <div id="load" style="text-align: center; color: white; display: block; height: 20px; width: 200px; background:blue; border: solid 1px black;"> <div id="bar" style="display: block; height: 20px; width: 0%; background:green;" ><div id="persent" style="position: relative; float:left; width:200px;">0%</div></div> </div> <br/> <div id="text"></div> <br/> <input id="btn" type='button' value='Выполнить сложную задачу' onclick='ProgressBar(0);'> <br/> </form> </body> </html> |
Данный код выводит на страницу кнопку с названием ‘Выполнить сложную задачу’, при нажатии на которую запускается процесс обработки сложной задачи с использованием ajax запросов. В коде присутствуют комментарии, поэтому не стану их дублировать, просто советую внимательно посмотреть что там написанно.
Если вы все сделали правильно, то у вас в корне сайта должны лежать два файла: index.php и ajax.js, в противном случаем вы можете скачать их одним архивом.
Запустите index.php вы увидите кнопку ‘Выполнить сложную задачу’. Нажмите на нее, и синяя полоса загрузки начнет заполняться зеленым цветом.
При достижении 100% вы увидите сообщение о успешном выполнении «сложной задачи».
Помните о том, что счетчик выполнения хранится в сессии на стороне сервера, поэтому для того, чтобы вновь посмотреть работу скрипта вам нужно будет перезапустить браузер, либо дописать скрипт самостоятельно таким образом, чтобы сессия сбрасывалась при достижении 100% результата.
Сегодня в статье с ужасным названием php+ajax полоса загрузки progressbar
мы рассмотрели, очень полезный на мой взгляд, механизм отслеживания выполнения задачи в процентах с выводом графического индикатора. Полоса загрузки, или попросту progressbar, будет полезен при синхронизации данных, при скачивании или закачивании файлов, а также при удаленной работе с чужим сайтом.
Читайте также похожие статьи:
Чтобы не пропустить публикацию следующей статьи подписывайтесь на рассылку по E-mail или RSS ленту блога.
Комментарии
Спасибо за инфо!
>»либо дописать скрипт самостоятельно»
Вот, решил дописать несколько строк:
после:
«session_start();//открываем сессию для записи»
добавить:
«if (($_POST[‘unset_sucsess’]==’reset’) and ($_SESSION[‘sucsess_part’]))
{
unset($_SESSION[‘sucsess_part’]);
}
»
и где:
» input id=»btn» type=’button’ value=’Выполнить сложную задачу’ onclick=’ProgressBar(0);’
»
добавить:
«input type=»submit» name=»unset_sucsess» onClick=»value=’reset'» id=»unset_sucsess» value=»сбросить сессию»
»
Знаки тега я убрал. чтобы сохранить код. 🙂
Но Ваш код никак не могу встроит к своему. 🙁
В отдельности все работает, но если встроит — что-то не так. 🙁
Попробую завтра. Может надо поменять текст: «Выполнить сложную задачу»
на: «Выполнить простую задачу»? 🙂
Шото оно вообще не пашит…
Перезагружается страница и сразу «выполнено».
Все должно работать.
Спасибо! Идея проста и понятна!
И ещё мне понравилось, как вы ловко, через каждые «пару» слов вставляете ключевые слова типа progress bar 🙂
вероятно последние строки кода должні віглядеть так:
Иначе, запустив скрипт второй раз мы ничего не увидим, ибо сессия уже выполнена на 100% ))
Так, это как?
а не проще ли сразу после else добавить
unset($_SESSION[‘sucsess_part’]);
тогда страницу можно обновлять в любое время и прогресс побежит с нуля )
может добавите код считывания файла?
Скрипт не работает. Тут же ведь нету даже возможности выбора файла.
В этом примере не нужна кнопка выбора файлов. У скрипта другие цели — реализация прогресбара. Если вы этого не поняли, перечитайте статью.
А если необходимо создать несколько таких процессов?
Создайте несколько, что мешает, это же ajax!
бесполезная статья, без загрузки файла хотя бы в примере.
Польза скрыта между строк 🙂
А если я, допустим получаю с удаленного сервера данные в json формате, посредством curl. Они всегда разной длинны. Удаленный сервер, никаких данных о конечном количестве данных не предоставляет. Единственное, есть маркер, который говорит о том что это последняя часть и запросы можно прекратить.
Как в таком варианте реализовать прогрессбар?
Здравствуйте Марк, классный блог у Вас. Читаю статью про прогресс бар, джиквери для меня тяжело(((. У меня есть сайт игры и мне нужен прогресс бар выполнения задания, ну например: купить пять персонажей, и прогресс бар заполняеться по мере выполнения. Сможете такое реализовать и сколько стоит работа, php я сам сделаю?
А если любой цикл добавить в Ваш код, то скрипт не отработает так как работает сейчас, а будет ждать пока отработает весь цикл… Вариант с ob_flush() — не предлагать, так как у большинства шаред хостингов связка nginx php-fpm, а там эта функция не работает так как нужно… Короче Ваш пример относительно не плох, но для очень уж простых задач, там где требуется длительное выполнение — он не катит!