Lab / php

Dropzone.JS + PHP Загрузка файлов на сервер

А этом уроке я покажу вам пример интеграции замечательного плагина Dropzone.js с вашим сайтом на php для загрузки файлов на сервер буквально в несколько строк кода.

Dropzone.JS это замечательная опенсурс библиотека написанная на ванильном JS предоставляющая вам интерфес для загрузки файлов drag and drop с предварительным просмотром файлов.

Для начала скачайте свежую версию библиотеки и её стили:

https://raw.githubusercontent.com/enyo/dropzone/master/dist/dropzone.js

https://raw.githubusercontent.com/enyo/dropzone/master/dist/dropzone.css

Затем создайте папку uploads и файлы index.php и upload.php

В качестве файла index php может выступать та часть вашего кода, которая содержит форму добавления материалов на сайт. В моём примере я создам чистую страницу с минимальной разметкой и подключеной библиотекой и стилями Dropzone.js:

<html>
<head> 
 
 <link href="css/dropzone.css" type="text/css" rel="stylesheet" />
 <script src="dropzone.min.js"></script>
 
</head>
<body>
 
 
 <form action="upload.php" class="dropzone"></form>
 
</body>
</html>

Как вы наверное заметили мы создали форму с экшеном upload.php, но не создавали никаких инпутов для прикрепления файлов, и не объявляли enctype формы. В этом нет никакой ошибки, все обрабатывается самой библиотекой DropzoneJS. Все, что нам нужно сделать, это присвоить форме класс dropzone. По умолчанию DropzoneJS находит все формы с данным классом и автоматически потрисовывет свой интерфейс.

Вы пожете открыть на исполнение в браузете страницу index.php и убедиться что библиотека срабатывает как задумано. Вот что у меня получилось:

Теперь давайте создадим обработчик загрузки для которого мы уже создали файл upload.php. Привожу пример моего простейшего кода загрузки:

<?php
$ds = DIRECTORY_SEPARATOR;
 
$storeFolder = 'uploads'; // Указываем папку для загрузки
 
if (!empty($_FILES)) { // Проверяем пришли ли файлы от клиента
 
 $tempFile = $_FILES['file']['tmp_name']; //Получаем загруженные файлы из временного хранилища
 
 $targetPath = dirname( __FILE__ ) . $ds. $storeFolder . $ds;
 
 $targetFile = $targetPath. $_FILES['file']['name'];
 
 move_uploaded_file($tempFile,$targetFile); // Перемещаем загруженные файлы из временного хранилища в нашу папку uploads
}
?>

Работа с загруженными файлами

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

Для этого обновляем файл upload.php до такого вида (вставлено условие else):

<?php
$ds = DIRECTORY_SEPARATOR; 
 
$storeFolder = 'uploads'; 
 
if (!empty($_FILES)) {
 
 $tempFile = $_FILES['file']['tmp_name']; 
 
 $targetPath = dirname( __FILE__ ) . $ds. $storeFolder . $ds; 
 
 $targetFile = $targetPath. $_FILES['file']['name']; 
 
 move_uploaded_file($tempFile,$targetFile);
 
} else { 
 $result = array();
 
 $files = scandir($storeFolder); //1
 if ( false!==$files ) {
 foreach ( $files as $file ) {
 if ( '.'!=$file && '..'!=$file) { //2
 $obj['name'] = $file;
 $obj['size'] = filesize($storeFolder.$ds.$file);
 $result[] = $obj;
 }
 }
 }
 
 header('Content-type: text/json'); //3
 header('Content-type: application/json');
 echo json_encode($result);
}
?>

Как вы можете видеть, мы добавили дополнительный оператор «else», когда HTTP-запрос не содержит файлов. Это используется для обнаружения уже сохраненных файлов на сервере. Давайте посмотрим, что они на самом деле делают.

  1. Функция PHP scandir просматривает папку uploads и возращает массив файлов или значение FALSE елси папка пуста.
  2. Перебираем возвращаемое значение из функции scandir и сохраняем в массив $ result. Помните, мы игнорируем "." И "..", поскольку scandir всегда будет возвращать "." И ".." в качестве допустимого содержимого, относящегося к текущему и предыдущему каталогу.
  3. Выводим правильные заголовки для разметки JSON, а также конвертируем PHP-массив в JSON-строку, используя функцию json_encode.

Теперь пришло время обновить index.php:

<html>
 
<head> 
 
<link href="css/dropzone.css" type="text/css" rel="stylesheet" />
 
<!-- 1 -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
 
<script src="dropzone.min.js"></script>
 
<script>
<!-- 3 -->
Dropzone.options.myDropzone = {
 init: function() {
 thisDropzone = this;
 <!-- 4 -->
 $.get('upload.php', function(data) {
 
 <!-- 5 -->
 $.each(data, function(key,value){
 
 var mockFile = { name: value.name, size: value.size };
 
 thisDropzone.options.addedfile.call(thisDropzone, mockFile);
 
 thisDropzone.options.thumbnail.call(thisDropzone, mockFile, "uploads/"+value.name);
 
 });
 
 });
 }
};
</script>
 
</head>
 
<body>
 
<!-- 2 -->
<form action="upload.php" class="dropzone" id="my-dropzone"></form>
 
</body>
 
</html>

Что мы тут накодили? Давайте разбиратся:

  1. Увы и ах, мы добавили библиотеку Jquery на нашу страницу. Это на самом деле не необходимость для DropzoneJs. Мы используем только ajax-функцию JQuery $ .get. Вы же на своё усмотрение можете реализовать подобные запросы на vue.js или что вам больше по душе.
  2. Мы добавили в форму элемент ID (my-dropzone). Это необходимо, для того что бы передать значения конфигурации в Dropzone. И для этого мы должны иметь уникальный индификатор указывающий на него. Таким образом мы можем настроить библиотеку, присвоив значения Dropzone.options.myDropzone.
  3. Инициализируем основную часть редактирования. То, что мы здесь сделали, - передали функцию прослушивания события init Dropzone. Это событие вызывается, когда Dropzone инициализируется.
  4. Получаем массив файлов из «upload.php» посредством ajax.
  5. Создаём mockFile, используя значения с сервера. MockFile - это просто объекты JavaScript со свойствами имени и размера. Затем мы явно вызываем функции Dropbox и добавляем иконки, чтобы поместить существующие файлы в область загрузки Dropzone и создать их миниатюры.

Если вы сделали всё корректно. Загрузите несколько изображений и перезагрузите страницу с формой. Ранее загруженные файлы должны автоматически отображаться в области Dropzone.