24 января 2014
8925
Drag drop загрузка, ajax загрузка файлов

Drag drop загрузка

JavaScript
Демонстрация » Скачать »

Здравствуйте! В этом уроке я расскажу, как асинхронно загружать файлы на сервер, при этом так, чтобы выбор файла можно было совершить, перетащив его в определенную область страницы. Такая асинхронная загрузка файлов называется Drag drop загрузка и является очень интересным решением, которое используется уже на многих сайтах. Ну если Вам все же нужна обычная загрузка, то могу посоветовать урок на тему загрузка картинки на сервер PHP.

 

Для начала, конечно, понадобиться создать элемент, который будет «ловить» файл. Кроме того, поместим в этот элемент span-тег для вывода сообщений о состоянии загрузки и input с типом file, чтобы не ограничивать выбор файла лишь перетаскиванием, а так же дать возможность пользователям выбрать файл нажатием на эту обозначенную область. Конечный вид такой структуры представлен ниже.

 

<div id="drop-zone">
         <span class="text">Нажмите сюда или перетащите файл для загрузки.</span>
        <input>
</div>

 

CSS к данному HTML коду ничем не примечателен, за исключением оформления поля input:

#file{
         width:100%;
         height:100%;
         display:block;
         position:absolute;
         top:0;
         left:0;
         opacity:0.01;
}

 

Так же описываем два класса, которые при добавлении к области «захвата» файла будут сигнализировать об успешной загрузке файла или же об ошибке, при возникновении таковой:

 

#drop-zone.success{
         background-color:#2ecc71;
}

#drop-zone.error{
         background-color:#e74c3c;
}

 

 

Теперь можем перейти к написанию «экшена» нашей страницы. Для начала запишем в переменные ссылки на объекты, к которым будем достаточно часто обращаться:

 

var dropZone = document.getElementById("drop-zone");
var msgConteiner = document.querySelector("#drop-zone .text");

 

После этого избавимся от событий по умолчанию при попадании курсора в нашу область приема файла следующим образом:

 

var eventClear = function (e) {
         e.stopPropagation();
         e.preventDefault();
}

dropZone.addEventListener("dragenter", eventClear, false);
dropZone.addEventListener("dragover", eventClear, false);

 

Далее назначим обработчики событий выбора файла как при перетаскивании, так и при выборе через поле input:

 

dropZone.addEventListener("drop", function (e) {
                   if(!e.dataTransfer.files) return;
                   e.stopPropagation();
                   e.preventDefault();
 
                   sendFile(e.dataTransfer.files[0]);

         }, false);

document.getElementById("file").addEventListener("change", function (e) {
                   sendFile(e.target.files[0]);
         }, false);

 

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

Эта функция отвечает за передачу файла серверу. Ее описание можете увидеть ниже.

 

var sendFile = function(file) {
// удаляем классы состояния, которые могли быть добавлены
// если пользователь уже пытался что либо загрузить
         dropZone.classList.remove("success");
         dropZone.classList.remove("error");

 

// делаем проверку при помощи регулярного выражения на тип файла
// ( в примере только изображения допускаем к загрузке)
         var re = /(.jpg|.jpeg|.bmp|.gif|.png)$/i;
         if (!re.exec(file.name)) {
                   msgConteiner.innerHTML = "Недопустимый формат файла!";
                   dropZone.classList.remove("success");
                   dropZone.classList.add("error");
         }
         else {
                   var fd = new FormData(); // создание объекта формы
                   fd.append("upfile", file); // добавление файла в форму отправки

                   var xhr = new XMLHttpRequest();
                   xhr.open("POST", "./upload.php", true);

                   xhr.upload.onprogress = showProgress;
                   xhr.onreadystatechange = statChange;
 
                   xhr.send(fd); // отправка на сервер
         }
}

 

 

Как Вы могли заметить, перед отправкой данных на сервер еще задаются два события, из которых первое отвечает за отображения прогресса загрузки, а второе за оповещение о результате загрузки. Действуют они следующим образом:

 

var showProgress = function(e) {
         if (e.lengthComputable) {
// расчет процента загрузки
                   var percent = Math.floor((e.loaded / e.total) * 100);
// вывод текущего процента
                   msgConteiner.innerHTML = "Загрузка... ("+ percent +"%)";
         }
};
 
var statChange = function (e) {
         if (e.target.readyState == 4) { // по завершению обработки запроса к серверу
                   if (e.target.status == 200) { // если запрос выполнен успешно
                            msgConteiner.innerHTML = "Загрузка успешно завершена!";
                            dropZone.classList.remove("error");
                            dropZone.classList.add("success");
                            document.getElementById("showUpFile").innerHTML = this.responseText;
                   } else { // иначе
                            msgConteiner.innerHTML = "Произошла ошибка!";
                            dropZone.classList.remove("success");
                            dropZone.classList.add("error");
                   }
         }
}

 

Завершающим этапом будет обработка получаемых сервером данных:

 

$uploaddir = getcwd() . DIRECTORY_SEPARATOR . "upload" . DIRECTORY_SEPARATOR;
$fileName = basename($_FILES["upfile"]["name"]);
$uploadfile = $uploaddir . $fileName;

// перемещаем загруженный файл в нужную нам директорию
move_uploaded_file($_FILES["upfile"]["tmp_name"], $uploadfile);

// отправляем ответ в виде тега img для отображения загруженного изображения
echo "<img src="./upload/" . $fileName . "">";

 

На этом написание скрипта асинхронной загрузки фала перетаскиванием завершено. Благодарю за внимание!