Сервис для
сео - оптимизаторов

Найди ошибки на сайте
Ошибки мешают продвижению сайта
Исправь ошибки на сайте
Сайт без ошибок продвигать легче
Получи новых клиентов
Новые клиенты принесут больше прибыль

Отслеживание прогресса загрузки с помощью PHP и JavaScript

  1. Процесс загрузки сеанса
  2. Создать форму
  3. Добавить стиль
  4. Функциональность на стороне клиента
  5. Прогресс в реальном времени
  6. Тонкая настройка поведения
  7. Резюме

Проблема, которая преследует веб-разработчиков на протяжении многих лет, заключается в том, как добавлять информацию в реальном времени в свои приложения, например индикатор выполнения для загрузки файлов. Пользователи нетерпеливы; они не хотят сидеть и ждать, пока браузер что-то делает, и задаются вопросом, не зависло ли оно или у них медленное соединение. Предоставление индикатора прогресса дает пользователям полезную информацию и позволяет им точно знать, что происходит.

На первый взгляд, вы можете подумать, что выполнить это можно легко, сначала получив размер файла с компьютера пользователя, а затем выполнив несколько простых вычислений для каталога на сервере, куда загружается файл. Если подумать, вы обнаружите, что все не так просто.

JavaScript может получить доступ к имени файла, типу и даже ширине и высоте локального изображения, но так было до HTML5, что он может получить доступ к размеру файла , К сожалению, HTML5 все еще не является законченным стандартом и не поддерживается одинаково во всех браузерах. Альтернативным решением является использование плагина Flash, Java или ActiveX; нет, спасибо, я сдам. Еще одно решение заключается в установке Альтернативный кеш PHP расширение, но оно может быть недоступно в зависимости от среды вашего хостинга, и это кажется излишним для такой маленькой задачи, как эта.

Казалось бы, все варианты чреваты неприятностями, и задача быстро стала головной болью. Но, по словам Йоды, «нет… есть другое».

Одна из многих причин, по которым я люблю PHP, заключается в том, что он облегчает, казалось бы, сложные задачи. Начиная с PHP 5.4, они сделали это снова с новым набором директив конфигурации, session.upload_progress.

В этой статье я покажу вам, как эту функцию можно использовать для создания простого индикатора выполнения загрузки без каких-либо внешних библиотек или зависимостей браузера. Сначала я расскажу, как это работает, а затем проведу вас через создание четырех файлов, необходимых для выполнения задачи (форма загрузки, немного JavaScript, немного CSS и файл для возврата статуса загрузки).

Процесс загрузки сеанса

Помимо обычных требований разрешить загрузку файлов, есть еще два, чтобы отслеживать прогресс. Директива session.upload_progress.enabled должна быть включена, и в вашей веб-форме должно быть скрытое поле с именем, указанным в директиве session.upload_progress.name. Когда для session.upload_progress.enabled задано значение true (как по умолчанию в PHP 5.4 и, вероятно, за его пределами) и во время загрузки отправляется $ _POST [ session.upload_progress.name ], информация о передаче файла становится доступной в суперглобальном выражении $ _SESSION. массив.

Вывод print_r () массива $ _SESSION будет выглядеть примерно так во время передачи файла:

Array ([upload_progress_myForm] => Array ([start_time] => 1323733740 [content_length] => 721127769 [bytes_processed] => 263178326 [done] => [files] => Array ([0] => Array ([field_name] = > userfile [name] => ubuntu-10.04.3-desktop-i386.iso [tmp_name] => [error] => 0 [done] => [start_time] => 1323733740 [bytes_processed] => 263178026))))

Когда вы разрабатываете локально или в быстрой сети и загружаете небольшие файлы, вы не сможете визуально наблюдать за прогрессом, потому что передача происходит так быстро. В этом случае вы можете попробовать перенести большой файл. Убедитесь, что настройки в вашем файле php.ini разрешают большие загрузки, в частности директивы post_max_size и upload_max_filesize, а затем убедитесь, что они являются нормальными значениями, когда вы приступаете к работе.

Создать форму

Первый файл, который я представлю, это форма загрузки. Просто для простоты, пример будет публиковать для себя и обрабатывать только один файл за раз. Кроме того, я не буду беспокоиться о сохранении файла после его загрузки.

Вот код для form.php:

<? php if ($ _SERVER ["REQUEST_METHOD"] == "POST" &&! empty ($ _ FILES ["userfile"])) {// move_uploaded_file ()}?> <html> <head> <title> Загрузка файла Индикатор выполнения </ title> <link rel = "stylesheet" type = "text / css" href = "style.css"> </ head> <body> <div id = "bar_blank"> <div id = "bar_color" > </ div> </ div> <div id = "status"> </ div> <form action = "<? php echo $ _SERVER [" PHP_SELF "];?>" method = "POST" id = "myForm "enctype =" multipart / form-data "target =" hidden_iframe "> <input type =" hidden "value =" myForm "name =" <? php echo ini_get ("session.upload_progress.name");?> "> <input type = "file" name = "userfile"> <br> <input type = "submit" value = "Начать загрузку"> </ form> <iframe id = "hidden_iframe" name = "hidden_iframe" src = "about : blank "> </ iframe> <script type =" text / javascript "src =" script.js "> </ script> </ body> </ html>

В этом примере код для фактической обработки файла был опущен, чтобы упростить задачу. Если вам интересно, как должен выглядеть такой код, ознакомьтесь со статьей Загрузка файлов с помощью PHP Тимоти Борончик.

После заголовка, который содержит заголовок страницы и таблицу стилей, вы увидите небольшую коллекцию элементов div. Div с идентификатором «bar_blank» является контейнером для индикатора выполнения. Div с идентификатором «bar_color» будет динамически обновляться по мере загрузки файла. Div «status» будет отображать числовое значение загруженного процента.

Форма настроена на отправку по тому же URL-адресу, а ее целевой атрибут указывает на скрытый элемент iframe. Отправка формы в скрытый фрейм позволяет удерживать посетителя на той же странице, пока работа выполняется в фоновом режиме. Фактически, это обычная практика при «загрузке Ajax-файла», поскольку невозможно отправить содержимое файла напрямую, используя объект JavaScript XmlHttpRequest.

Внутри формы появляется специальное скрытое поле, необходимое для заполнения массива $ _SESSION, за которым следует кнопка ввода и отправки файла для загрузки. Отправка формы вызовет функцию JavaScript с именем startUpload (), которая будет определяться включенным файлом JavaScript.

Внизу страницы находится скрытый фрейм, в который будет отправлена ​​форма, и импорт файла script.js.

Добавить стиль

Следующий файл style.css довольно прост. Я определил размер контейнера индикатора выполнения и присвоил ему черную рамку размером 1 пиксель, цвет индикатора выполнения во время загрузки, а также iframe и индикатор выполнения скрыты.

#bar_blank {border: solid 1px # 000; высота: 20 пикселей; ширина: 300 пикселей; } #bar_color {background-color: # 006666; высота: 20 пикселей; ширина: 0px; } #bar_blank, #hidden_iframe {display: none; }

Функциональность на стороне клиента

Файл script.js является самым большим из группы файлов. Он содержит шесть функций, которые я расскажу ниже. Многие люди любят использовать jQuery для предоставления некоторых функций здесь, и вы, безусловно, можете сделать это, если хотите, но я лично предпочитаю подход старой школы. Подобно тому, как японцы придают большее значение товарам ручной работы, я просто чувствую большую страсть к коду, если он мой.

function toggleBarVisibility () {var e = document.getElementById ("bar_blank"); e.style.display = (e.style.display == "блок")? "нет": "блок"; } function createRequestObject () {var http; if (navigator.appName == "Microsoft Internet Explorer") {http = новый ActiveXObject ("Microsoft.XMLHTTP"); } else {http = new XMLHttpRequest (); } вернуть http; } function sendRequest () {var http = createRequestObject (); http.open ("GET", "progress.php"); http.onreadystatechange = function () {handleResponse (http); }; http.send (нуль); } function handleResponse (http) {var response; if (http.readyState == 4) {response = http.responseText; document.getElementById ("bar_color"). style.width = response + "%"; document.getElementById ("status"). innerHTML = response + "%"; if (response <100) {setTimeout ("sendRequest ()", 1000); } else {toggleBarVisibility (); document.getElementById ("status"). innerHTML = "Done."; }}} function startUpload () {toggleBarVisibility (); setTimeout ("sendRequest ()", 1000); } (function () {document.getElementById ("myForm"). onsubmit = startUpload;}) ();

Функция toggleBarVisibility () устанавливает соответствующий стиль в div «bar_blank» для отображения или скрытия индикатора выполнения по мере необходимости. Первоначально он начинается скрытно, но будет отображаться после начала загрузки и снова скрываться после завершения загрузки.

Функция createRequestObject () создает объект XMLHttpRequest или ActiveXObject на основе браузера пользователя. Вероятно, именно эту функцию большинство людей хотели бы использовать в jQuery или какой-либо другой среде JavaScript.

Функция sendRequest () запрашивает файл progress.php с помощью запроса GET, а затем вызывает функцию handleResponse () для обработки возвращаемых данных.

Функция handleResponse () обрабатывает ответ от файла progress.php, который будет иметь значение от 1 до 100 в зависимости от хода загрузки файла. Я также обновляю div «status» соответствующим значением. Если текущий процент ниже 100, тогда я вызываю встроенную в JavaScript функцию setTimeout (), чтобы через 1 секунду отправить другой запрос на обновление (вы можете изменить это значение соответствующим образом), в противном случае я снова скрываю индикатор выполнения и устанавливаю статус в "Готово."

Функция startUpload () делает панель загрузки видимой и отправляет запрос на обновление после задержки в 1 секунду. Эта небольшая задержка необходима для того, чтобы дать время для загрузки.

Последняя функция - это самозаполняющаяся анонимная функция, которая регистрирует startUpload () с событием отправки формы.

Прогресс в реальном времени

Последний файл, который объединяет все, - это файл progress.php:

<? php session_start (); $ key = ini_get ("session.upload_progress.prefix"). "Myform"; if (! empty ($ _ SESSION [$ key])) {$ current = $ _SESSION [$ key] ["bytes_processed"]; $ total = $ _SESSION [$ key] ["content_length"]; echo $ current <$ total? ceil ($ current / $ total * 100): 100; } else {echo 100; }

Скрипт выполняет простую математическую обработку текущего количества переданных байтов, разделенного на общий размер файла, умноженного на 100 и округленного до процента.

Информация о передаче основывается на конкатенации значения директивы session.upload_progress.prefix и скрытого значения поля session.upload_progress.name. Поскольку моя форма прошла «myForm», ключ сессии определяется с помощью ini_get («session.upload_progress.prefix»). "Myform".

Вот скриншот индикатора выполнения в действии:

Тонкая настройка поведения

PHP предоставляет некоторые дополнительные директивы, чтобы помочь точно настроить поведение загрузки сеанса, о которой вы должны знать. Например, session.upload_progress.cleanup, для которого по умолчанию установлено значение 1, очищает дополнительные данные сеанса сразу после завершения загрузки. Вы должны быть осторожны, чтобы избежать потенциального состояния гонки.

Еще раз взгляните на код в progress.php, и вы заметите, что я проверяю, является ли $ _SESSION [$ key] пустым или нет, прежде чем продолжить. Мои функции JavaScript отключаются каждую секунду, пока результат, возвращаемый из файла progress.php меньше 100. Если включен файл session.upload_progress.cleanup, и мой сценарий получает 99% загрузки, а через 1/2 секунды загрузка завершается $ _SESSION [$ key] не будет существовать для следующей проверки. Если я не учту это, тогда моя функция JavaScript может продолжать работать даже после завершения загрузки.

Еще две директивы: session.upload_progress.freq и session.upload_progress.min_freq, которые определяют частоту обновления сеанса. Значение freq может быть задано либо в байтах (т.е. 100), либо в процентах от общего количества байтов (т.е. 2%). Значение min_freq дается в секундах и указывает минимальное количество секунд между обновлениями. Очевидно, что если min_freq был настроен на обновление каждую 1 секунду, для вашего JavaScript было бы бессмысленно проверять каждые 100 миллисекунд.

Резюме

Теперь вы должны четко понимать, как создать индикатор выполнения для загрузки файлов с помощью функции выполнения загрузки сеанса. В дальнейшем я рекомендую вам поэкспериментировать с загрузкой нескольких файлов, давая возможность отменить текущую загрузку, используя $ _SESSION [$ key] ["cancel_upload"] или любые другие идеи, которые ваш разум может придумать. Пожалуйста, поделитесь в комментариях своим опытом и улучшениями, которые вы сделали для других, чтобы извлечь из этого пользу!

Изображение через file404 / Shutterstock

Php if ($ _SERVER ["REQUEST_METHOD"] == "POST" &&! empty ($ _ FILES ["userfile"])) {// move_uploaded_file ()}?
Php echo $ _SERVER [" PHP_SELF "];?
Php echo ini_get ("session.upload_progress.name");?
Display = (e.style.display == "блок")?