Загрузка изображений. Jquery, PHP 


Загрузка изображений. Jquery, PHP

Опубликовано

Загрузка изображений неотъемлемая часть любого веб-приложения, и веб-разработчик всегда старается сделать ее наиболее удобной для пользователя.

Стандартная HTML форма не дает нам возможность наблюдать за процессом загрузки да и к тому же данные отправляются с перезагрузкой страницы, это очень неудобно. В интернете можно найти множество плагинов, чтобы доработать стандартную форму и реализовать более удобную отправку данных. Однако можно обойтись и без сторонних плагинов, реализовав форму загрузки, используя библиотеку Jquery.

Отправка изображения на сервер, без перезагрузки документа

Создайте страницу, в заголовке подключите библиотеку jquery, в тело документа вставьте форму с уникальным идентификатором id="formupload".

<!doctype html>
<html>
<head>
  <meta charset="utf8" />
  <title>Image Upload</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
</head>
<body>
<form action="upload-images.php" method="post" enctype="multipart/form-data"  id="formupload">
  <input type="file" name="file" id="fileupload" />
  <button>Загрузить</button>
</form>
</body>
</html>

Далее необходимо создать обработчик событий на js, который будет отлавливать момент отправки формы, обрабатывать ее данные и уже посредством Ajax отправлять их (наше изображение) на сервер.

В заголовок документа после подключения библиотеки Jquery, вставим следующий js код.

<script>
$(document).ready(function(){
  $("#formupload").submit(function(){
    var type = $(this).attr("method");
    var url = $(this).attr("action");
    var formData = new FormData($(this)[0]);
    $.ajax({
      url: url,
      data: formData,
      dataType: "json",
      type: type,
      contentType: false,
      processData: false,
      success: function (data){
        $("<img>")
        .attr("src",data.filelink)
        .appendTo($("#formupload"));
      }
    });
    return false;
  });
});
</script>

Код срабатывает, когда пользователь кликает на кнопку “Загрузить”. Форма пытается отправить данные на сервер, однако наш обработчик событий отлавливает этот момент.

Скрипт считывает свойства указанные в форме (метод отправки и путь до серверного сценария). Далее используя объект FormData, подготавливается форму для отправки ее Ajax запросом. Функция, опции success, выполнится в случае успешной отправки формы и получения результата, от серверного сценария в формате json , т.к. dataType: "json" (Серверный сценарий будет рассмотрен ниже, но заранее хочу пояснить, что в результате успешной загрузки изображения, от сервера приходит путь до картинки, в переменной filelink). Далее создается новый элемент <img>, которому присваивается путь загруженного изображения и помещается в форму. return false; в конце функции предотвращает отправку формы, а значить и перезагрузки страницы.

Серверный сценарий обработки изображений

Данные формы отсылаются на сервер, где они будут обработаны php скриптом указанным в параметре url функции $.ajax. Далее расположен базовый обработчик (код взят с сайта imperavi.com)

<?php
//Путь до папки с изображениями, где хранятся загруженные изображения
$dir = "/sitecom/images/"; 
$_FILES["file"]["type"] = strtolower($_FILES["file"]["type"]);

if ($_FILES["file"]["type"] == "image/png"
|| $_FILES["file"]["type"] == "image/jpg"
|| $_FILES["file"]["type"] == "image/gif"
|| $_FILES["file"]["type"] == "image/jpeg"
|| $_FILES["file"]["type"] == "image/pjpeg")
{
  // Новое имя изображения
  $filename = md5(date("YmdHis")).".jpg";
  $file = $dir.$filename;

  // Копирование файла 
  move_uploaded_file($_FILES["file"]["tmp_name"], $file);

  // Ответ сервера: путь до загруженного файла
  $array = array(
    "filelink" => "images/".$filename
  ); 
  echo stripslashes(json_encode($array)); 
}
?>

Индикаторы загрузки или прелоадеры

На данном этапе у нас уже готова загрузка изображения, но все, же есть неудобство т.к. пользователь не имеет визуального наблюдения за процессом загрузки.

Далее представлены два варианта прелоадера:

Статичный индикатор

Статичный, т.к. он не дает представления о количестве загруженных данных, а лишь появляется на странице в момент оправки данных на сервер, и скрывается, когда данные отправлены. В качестве индикатора можете создать gif изображение, с помощью одного из специализированных онлайн сервисов, к примеру ajaxload.info

Вставьте в форму или другое местоположение на странице html код прелоадера, в данном случае в форму добавлен блок <div class="preloader">…</div>

Также необходимо внести изменения в js скрипт, добавив методы ajaxStart и ajaxStop, соответственно код находящийся в первом будет выполняться при начале выполнения ajax запроса, второй при его остановке.

И добавить CSS стиль, скрывающий прелоадер при первоначальной загрузке документа.

<script>
$(document).ready(function(){

  $("#formupload").submit(function(){
    // загрузка изображения
  });

})
.ajaxStart(function(){
  $(".preloader").show()
})
.ajaxStop(function(){
  $(".preloader").hide()
});
</script>

<style>
.preloader{
  display: none;
}
</style>
</head>
<body>

<form action="image_upload.php" method="post" enctype="multipart/form-data" id="formupload">

  <input type="file" name="file" id="fileupload" />
  <button>Загрузить</button>

  <div class="preloader">
    <img src="/imgs/loader/loader_review.gif" />
  </div>

</form>

Динамичный индикатор загрузки

Динамический индикатор в отличие от статического, показывает пользователю процент загруженных данных.

HTML & CSS: Для создания простейшего “прогресс бара” нам понадобится два блока <div>, первый имеет фиксированную ширину, второй вложен в первый, будет наращиваться на величину полученную при выполнении js кода.

<style>
…
</style>
…
<form>
…
  <div class="progress">
    <div></div>
  </div>

</form>

JS: Чтобы получить информацию о количестве загруженных данных воспользуемся объектом XMLHTTPRequest. Далее представлена функция, с ее помощью можно слушать сервер для получения данных о процессе загрузки. Переменная percentComplete, рассчитывает какое количество данных уже загружено.

xhr: function()
{
  var xhr = new window.XMLHttpRequest();
  xhr.upload.addEventListener("progress", function(evt){
    if (evt.lengthComputable) {
      var percentComplete = evt.loaded / evt.total;
    }
  }, false);
return xhr;
}

Совместив все вместе, получим следующий код:

<script>
$(document).ready(function(){

 $("#formupload").submit(function(){
  var type = $(this).attr("method");
  var url = $(this).attr("action");
  var formData = new FormData($(this)[0]);
  $.ajax({

   xhr: function(){
    var xhr = new window.XMLHttpRequest();
    xhr.upload.addEventListener("progress", function(evt){
     if (evt.lengthComputable) {
      var percentComplete = evt.loaded/evt.total;
      //Узнаем ширину статичного блока прогресс бара
      var length = parseInt($(".progress").width());
      //Наращиваем ширину вложенного блока, прогресс бара
      $(".progress")
      .children("div")
      .width(Math.round(percentComplete*length));
     }
    }, false);
    return xhr;
   },

   url: url,
   data: formData,
   dataType: "json",
   type: type,
   contentType: false,
   processData: false,
   success: function (data){
     $("<img>")
     .attr("src",data.filelink)
     .appendTo($("#formupload"));
   }
  });
  return false;
 });
});
</script>

<style>
.progress{
  width: 500px;
  height: 10px;
  border: 1px solid black;
}
.progress > div{
  width: 0px;
  height: 10px;
  position: relative;
  background-color: black;
}
</style>

</head>
<body>

<form action="image_upload.php" method="post" enctype="multipart/form-data" id="formupload">

  <input type="file" name="file" id="fileupload" />
  <button>Загрузить</button>

  <div class="progress">
    <div></div>
  </div>

</form>

По желанию, вы можете совмещать два типа прелоадера вместе.

Размер загружаемого файла

Иногда бывает необходимо узнать размер загружаемого файла, перед отправкой его на сервер, следующий код показывает, как это сделать

<script>
$(document).ready(function(){

 $("#formupload").submit(function(){

  var size = parseInt($("#fileupload")[0].files[0].size);
  //Мб
  size = Math.round(((size/1024)/1024));
  if (size>2)
  {
    alert("Файл больше чем 2 мб.");
    return false;
  }

  // загрузка изображения

 });
});
</script>
…
<form action="image_upload.php" method="post" enctype="multipart/form-data" id="formupload">

  <input type="file" name="file" id="fileupload" />
  <button>Загрузить</button>

</form>