Блог веб разработки статьи | видеообзоры | исходный код

Блог веб разработки статьи | видеообзоры | исходный код

webfanat вконтакте webfanat youtube

Индикатор загрузки файлов

Индикатор загрузки файлов

Всем привет! Сегодня будет рассмотрено как сделать простенький индикатор для отображения процесса загрузки файлов на сервер. Итак, поехали!

Иногда бывает просто необходимо чем то заполнить возникшую паузу в процессе загрузки файла(ов) на сервер чтобы пользователь ясно понимал что процесс идет.

Причинами долгой загрузки может быть:

1. Плохое(медленное) соединение с интернетом

2. Большой вес загружаемых файлов

Для решения этой задачи идеально подойдет технология ajax в инструментариях которой есть механизм отслеживания передачи байтов на сервер.

Для начала создадим серверную часть в файле server.php

<?php

define('EXT', array('mp4', 'mp3'));
define('SIZE_MB', 100);

if(count($_FILES) === 0 || count($_POST) === 0){

  echo json_encode(array('message'=> 'Переданы не все данные'), true);
  die();
}

if(!isset($_POST['name']) || !isset($_POST['email']) || trim($_POST['name']) === "" || trim($_POST['email']) === ""){

    echo json_encode(array('message'=> 'Не передано имя и/или email'), true);
  die();
}

if(!isset($_FILES['media'])){
     echo json_encode(array('message'=> 'Не удалось получить загруженный файл'), true);
   die();
  }
$count_file = 0;
  for($i = 0; $i < count($_FILES['media']['tmp_name']); $i++){
    if(trim($_FILES['media']['name'][$i]) === ''){
      continue;
    }
    if(trim($_FILES['media']['type'][$i]) === ''){
      continue;
    }
    if(trim($_FILES['media']['tmp_name'][$i]) === ''){
      continue;
    }
    $ext = pathinfo($_FILES['media']['name'][$i], PATHINFO_EXTENSION);
    if(!in_array($ext, EXT)){
      continue;
    }
    $size = $_FILES['media']['size'][$i] / 1000000;
    if($size >= SIZE_MB){
      continue;
    }

      $path = $_SERVER['DOCUMENT_ROOT'].'upload/'.base64_encode(openssl_random_pseudo_bytes(10)).'.'.$ext;
      if(!@move_uploaded_file($_FILES['media']['tmp_name'][$i], $path)){
        continue;
      }
      $count_file++;
  }

  if($count_file === 0){
    echo json_encode(array('message'=> 'Файлы не были загружены'), true);
  die();
  }

  echo json_encode(array('message'=> 'Данные успешно отправлены'), true);

Весь механизм мы взяли из статьи посвященной загрузке файлов на сервер. Здесь идут несколько ограничений по общему весу файлов (не более 100 мб) и расширению (допускаются только файлы с расширением mp3, mp4). С этим я думаю все понятно!

Теперь рассмотрим клиентскую часть в index.html

<style>
	 #progress{
			 position:fixed;
			 top:0%;
			 left:0%;
			 width:100%;
			 height:100%;
			 z-index:1000000;
			 background:rgba(0, 0, 0, 0.7);
			 display:none;
	 }
		#progress div{
				position:absolute;
				top:50%;
				left:50%;
				transform:translate(-50%, -50%);
				background:white;
				padding:20px;
				text-align:center;
		}
</style>
<div id="progress" >
	 <div>
			 <h4>Загружено</h4>
			 <p id="load-progress">0%</p>
			 <progress id="progressbar" value="0" max="100"></progress>
			 <p id="size-progress"></p>
	 </div>
</div>
<form method="post" action="server.php" enctype="multipart/form-data">
  <input name="name" placeholder="Введите  имя" type="text" required/>
  <input name="email" placeholder="Введите  email" type="email" required/>
  <label>Загрузите медиафайл(mp3, mp4)</label>
      <input type="file"  name="media[]" multiple/>
    <button>Отправить</button>
</form>
<script>
function loadProcess(a, len){
   var one =  len / 100;
   var proc = (a / one).toFixed(1);
  document.querySelector('#progressbar').value = (a / one);
	document.querySelector('#load-progress').innerText = proc + '%';
  document.querySelector('#size-progress').innerText = "Загружено: " + a.toFixed(2) + "МБ из " + len.toFixed(2) + "МБ";
}


document.querySelector('form').addEventListener('submit', function(e){
  e.preventDefault();
  var data = new FormData(this);

  var receivedLength = 0, print = 0;
  var xhr = new XMLHttpRequest();
      xhr.open("POST", '/server.php');
      xhr.responseType = 'json';
  if (xhr.upload) {

     document.querySelector('#progress').style.display = "block";

     xhr.upload.addEventListener('progress', function(e) {
        if (e.lengthComputable) {
               loadProcess((e.loaded / 1000000), (e.total / 1000000));
        }
    },false);


  xhr.onload = function(){
    if(this.status === 200){
      var res = this.response;

      alert(res['message']);
      if(res['message'] === 'Данные успешно отправлены'){
        document.querySelector('form').reset();
      }
    }else{
      alert('Страница не найдена!');
    }
     document.querySelector('#progress').style.display = "none";
  };
    xhr.onerror = function(){
      alert('Проверьте соединение с интернетом!');
       document.querySelector('#progress').style.display = "block";
    };
    xhr.send(data);

  }

});
</script>

Здесь при отправке формы с заполненными полями и прикрепленном файле мы можем наблюдать процесс загрузки в виде бегущей дорожки(индикатора) + отображении сколько из скольки МБ загружено.

За вывод информации загрузки отвечает функция loadProcess() которая принимает два параметра: количество МБ загруженных в определенную единицу времену и общее количество загружаемых МБ. Эти параметры мы получаем из события 'progress' объекта xhr(ajax).

xhr.upload.addEventListener('progress', function(e) {
    if (e.lengthComputable) {
           loadProcess((e.loaded / 1000000), (e.total / 1000000));
    }
},false);

e.lengthComputable - возвращает true при загрузке определенной части данных

e.loaded - количество загруженных байтов за определенную единицу времени

e.total - общее количество байтов которые будут загружены по завершению загрузки

Этот же механизм для отображения процесса загрузки можно использовать в обратном направлении. То есть когда мы что то скачиваем с сервера.

Пример:

<style>
	 #progress{
			 position:fixed;
			 top:0%;
			 left:0%;
			 width:100%;
			 height:100%;
			 z-index:1000000;
			 background:rgba(0, 0, 0, 0.7);
			 display:none;
	 }
		#progress div{
				position:absolute;
				top:50%;
				left:50%;
				transform:translate(-50%, -50%);
				background:white;
				padding:20px;
				text-align:center;
		}
</style>
<div id="progress" >
	 <div>
			 <h4>Загружено</h4>
			 <p id="load-progress">0%</p>
			 <progress id="progressbar" value="0" max="100"></progress>
			 <p id="size-progress"></p>
	 </div>
</div>

<button id="load">Скачать файл с сервера</button>
<script>

  function loadProcess(a, len){
     var one =  len / 100;
     var proc = (a / one).toFixed(1);
    document.querySelector('#progressbar').value = (a / one);
    document.querySelector('#load-progress').innerText = proc + '%';
    document.querySelector('#size-progress').innerText = "Загружено: " + a.toFixed(2) + "МБ из " + len.toFixed(2) + "МБ";
  }

  document.querySelector('#load').addEventListener('click', function(){
    var xhr = new XMLHttpRequest();
    xhr.open('GET', '/video.mp4');
    xhr.responseType = 'blob';
    if(xhr.upload){
      document.querySelector('#progress').style.display = "block";

      xhr.addEventListener('progress', function(e) {
         if (e.lengthComputable) {
                loadProcess((e.loaded / 1000000), (e.total / 1000000));
         }
     },false);
      xhr.onload = function(){
        var url = URL.createObjectURL(this.response),
        a = document.createElement('a');
        a.href = url;
        a.setAttribute('download', 'video.mp4');
        a.click();
          document.querySelector('#progress').style.display = "none";
      };
      xhr.send();
    }
  });

</script>

В данном примере мы с сервера скачиваем некий файл video.mp4. Обратите внимание что здесь немного по другому вызывается событие 'progress'.

xhr.addEventListener('progress', function(e) {
         if (e.lengthComputable) {
                loadProcess((e.loaded / 1000000), (e.total / 1000000));
         }
     },false);

При загрузке файлом мы вызывали событие через свойство upload(xhr.upload) здесь же мы вызываем событие напрямую. Для тех кто еще не понял вот сравнительный пример с комментариями:

//Процесс загрузки на сервер(используется свойство upload)
xhr.upload.addEventListener('progress', function(e) {
    if (e.lengthComputable) {
           loadProcess((e.loaded / 1000000), (e.total / 1000000));
    }
},false);


// процесс загрузки с сервера
xhr.addEventListener('progress', function(e) {
     if (e.lengthComputable) {
            loadProcess((e.loaded / 1000000), (e.total / 1000000));
     }
},false);

По сути с помощью xhr.upload мы отображаем процесс передачи байтов на сервер(запрос), а при использовании просто xhr процесс приема байтов с сервера(ответ).

Вот в принципе и все что я хотел вам рассказать про отображение процесса загрузки данных. Конечно данный механизм лучше использовать когда вы осуществляете процесс обмена большими данными, так как в ином случае особой необходимости его использовать нет, вы просто не увидите процесса(из за малого объема данных).

Надеюсь данная статья была для вас полезной! Не забывайте подписываться на группу Вконтакте и переходите на мой канал Youtube.

Желаю успехов и удачи! Пока.

Оцените статью:

Статьи

Комментарии

Внимание!!! Все комментарии проходят модерацию перед публикацией!

В данном разделе пока нет комментариев!

Реклама

Запись экрана

Данное расширение позволяет записывать экран и выводит видео в формате webm