Skip to content

Все для WordPress, веб-розробки — і не тільки

📤 Завантаження файлів перетягуванням з Dropzone.js і PHP

📤 Завантаження файлів перетягуванням з Dropzone.js і PHP

Користувачі очікують, що файли на сайт можна закинути, просто перетягнувши їх у вікно браузера. Кнопка «Виберіть файл» і провідник уже сприймаються як зайвий рух. Але писати drag-and-drop з нуля на JavaScript — це кілька сотень рядків коду, прогрес-бари, прев’ю та обробка помилок. На щастя, є готова бібліотека, яка закриває все це з коробки.

Dropzone.js — це open-source JavaScript-бібліотека для завантаження файлів перетягуванням. Показує прев’ю зображень, прогрес-бар і не потребує jQuery. Працює з будь-якою серверною мовою: PHP, Node.js, Python. У цьому посібнику, повний цикл від встановлення до продакшен-налаштування за шість кроків.

💡 Швидкий огляд:

  • У чому суть: бібліотека Dropzone.js перетворює будь-який HTML-елемент на зону для перетягування файлів з AJAX-надсиланням на сервер.
  • Як встановити: CDN-посилання (unpkg або jsDelivr) чи npm-пакет, обидва варіанти розглянуто в першому кроці.
  • Як обробити на сервері: PHP-скрипт приймає файл через $_FILES, як звичайну форму, третій крок із готовим кодом.
  • Де застосувати: контактні форми з вкладеннями, завантаження аватарів, масовий імпорт зображень у галерею WordPress.

Крок 1: Встановлення Dropzone.js

Найшвидший спосіб, підключити бібліотеку через CDN. Додайте цей тег у <head> сторінки:

1<script src="https://unpkg.com/dropzone@5/dist/min/dropzone.min.js"></script>

CSS-файл підключається окремо:

1<link rel="stylesheet" href="https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" />

Якщо користуєтеся збирачем, встановлюйте через npm:

1npm install dropzone

І імпортуйте у своєму JS-файлі:

1import Dropzone from "dropzone";

Зверніть увагу: версія 5.9, остання стабільна на початок 2026 року. Шоста версія в статусі beta, для продакшену поки не рекомендована. Репозиторій проєкту тепер живе за адресою github.com/dropzone/dropzone (раніше був enyo/dropzone).

Крок 2: Базова HTML-розмітка та ініціалізація

Створіть форму з класом dropzone. Dropzone автоматично знайде її та перетворить на зону для перетягування:

1<form action="/upload.php"
2 class="dropzone"
3 id="my-dropzone"></form>

Усе. Коли користувач перетягне файл у цю форму, бібліотека надішле його AJAX-запитом за адресою з атрибута action. На серверному боці файл потрапить у $_FILES['file'], так само як при звичайному надсиланні через <input type="file">.

Розробник пише код для завантаження файлів

Якщо потрібен fallback для браузерів без JavaScript, додайте всередину форми звичайне поле:

1<form action="/upload.php" class="dropzone">
2 <input name="file" type="file" multiple />
3</form>

Кнопка «Виберіть файл» буде показана лише тоді, коли JavaScript недоступний. Коли JS увімкнено, Dropzone приховає її та відобразить свою зону перетягування.

Крок 3: Обробка файлів на сервері

PHP-скрипт приймає завантаження так само, як звичайну форму. Мінімальний робочий варіант:

1<?php
2if (!empty($_FILES)) {
3 $uploadDir = __DIR__ . '/uploads/';
4
5 if (!is_dir($uploadDir)) {
6 mkdir($uploadDir, 0755, true);
7 }
8
9 $originalName = basename($_FILES['file']['name']);
10 $targetPath = $uploadDir . time() . '_' . $originalName;
11
12 if (move_uploaded_file($_FILES['file']['tmp_name'], $targetPath)) {
13 http_response_code(200);
14 echo json_encode(['status' => 'ok', 'file' => $targetPath]);
15 } else {
16 http_response_code(500);
17 echo json_encode(['status' => 'error', 'message' => 'Не удалось сохранить файл']);
18 }
19}

Що тут відбувається:

  • Скрипт створює папку uploads/, якщо її немає.
  • До оригінального імені файлу додається time(), це запобігає конфлікту імен.
  • basename() обрізає можливі path-traversal-атаки (спроби вийти за межі папки через ../).
  • Dropzone очікує від сервера HTTP 200, інакше вважає завантаження невдалим і показує помилку.

Для продакшену додайте ще перевірку розширення та MIME-типу:

1$allowed = ['jpg', 'jpeg', 'png', 'gif', 'pdf', 'zip'];
2$ext = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
3
4if (!in_array($ext, $allowed)) {
5 http_response_code(400);
6 echo json_encode(['status' => 'error', 'message' => 'Недопустимый тип файла']);
7 exit;
8}

Крок 4: Обмеження кількості, розміру та типу файлів

Три найбільш затребувані налаштування Dropzone конфігуруються через JavaScript-конфіг:

1Dropzone.options.myDropzone = {
2 maxFiles: 10,
3 maxFilesize: 5, // В мегабайтах
4 acceptedFiles: 'image/*,.pdf',
5 dictDefaultMessage: 'Перетащите файлы сюда или кликните для выбора'
6};

Розбір опцій:

  • maxFiles, скільки файлів користувач може завантажити за раз. Типово обмежень немає, у прикладі, не більше 10.
  • maxFilesize, максимальний розмір одного файлу в мегабайтах. Значення 5 означає 5 МБ. У старих версіях бібліотеки типово стояло 256 МБ, в актуальній 5.x, теж 256, тому явно вкажіть свій ліміт.
  • acceptedFiles, рядок із MIME-типами через кому. Шаблон image/* дозволяє будь-які зображення, .pdf додає PDF до списку. Повний перелік MIME-типів дивіться в документації Dropzone.
  • dictDefaultMessage, український текст, який користувач бачить у порожній зоні завантаження.

Ключ myDropzone у Dropzone.options.myDropzone — це camelCase-версія HTML-атрибута id="my-dropzone". Дефіси відкидаються, кожне наступне слово з великої літери: my-dropzonemyDropzone, file-upload-areafileUploadArea.

Опція resizeWidth та resizeHeight дозволяє зменшувати зображення на клієнті до відправлення. Це економить трафік користувача та розвантажує сервер, особливо коли відвідувачі завантажують фотографії з телефону по 10-15 МБ кожна. Вказуйте обидва параметри одночасно:

1Dropzone.options.myDropzone = {
2 resizeWidth: 1200,
3 resizeHeight: 1200,
4 resizeQuality: 0.8,
5 resizeMethod: 'contain'
6};

Метод contain вписує зображення в задані межі без обрізання, crop обрізає до точних розмірів. Якість 0.8 на практиці не відрізнити від оригіналу, але вона зменшує розмір файлу в 4-7 разів. Важливо: ресайз працює лише з image-файлами, PDF та архіви пропускаються як є. Браузер виконує ресайз через Canvas API, додаткові бібліотеки не потрібні.

Крок 5: Ручне відправлення файлів

Типово Dropzone відправляє файл на сервер одразу після додавання. Це не завжди зручно: іноді потрібно дати користувачеві заповнити поля форми поруч із зоною завантаження, а відправити все однією кнопкою.

Вимикаємо автозавантаження прапорцем autoProcessQueue: false і вішаємо відправлення на зовнішню кнопку:

1Dropzone.options.myDropzone = {
2 autoProcessQueue: false,
3 maxFilesize: 5,
4 init: function () {
5 const myDropzone = this;
6 const submitBtn = document.querySelector('#btnUpload');
7
8 submitBtn.addEventListener('click', function () {
9 if (myDropzone.getQueuedFiles().length === 0) {
10 alert('Нет файлов для загрузки');
11 return;
12 }
13 myDropzone.processQueue();
14 });
15
16 this.on('success', function (file, response) {
17 console.log('Файл загружен:', file.name);
18 });
19 }
20};

Ключовий момент тут, метод processQueue(). Він запускає відправлення всіх файлів, накопичених у черзі. Подія success спрацьовує для кожного файлу окремо, можна оновити інтерфейс або записати ID завантаженого файлу в приховане поле форми.

Крок 6: Передавання додаткових даних разом із файлом

Іноді потрібно прикріпити до завантаження службові параметри: ID користувача, статус документа, вибрану категорію. У Dropzone для цього є подія sending:

1Dropzone.options.myDropzone = {
2 init: function () {
3 this.on('sending', function (file, xhr, formData) {
4 formData.append('status', 'draft');
5 formData.append('user_id', currentUserId);
6 });
7
8 this.on('success', function (file, responseText) {
9 console.log('Готово:', responseText);
10 });
11 }
12};

Подія sending викликається безпосередньо перед XMLHttpRequest-відправленням. Третій аргумент formData, стандартний об’єкт FormData, до якого можна додати будь-які пари «ключ-значення» через append(). На серверному боці ці параметри читаються з $_POST['status'] та $_POST['user_id'].

Практичний сценарій: користувач вибирає альбом у випадному списку поруч із Dropzone-зоною, і ID альбому надходить разом із кожним файлом, сервер одразу розкладає завантаження по потрібних папках.

Безпека: три правила, які не можна ігнорувати

Перед тим як віддавати Dropzone на продакшен, перевірте три моменти.

Перше. Завжди валідуйте тип і розмір файлу на серверному боці, навіть якщо вже налаштували acceptedFiles і maxFilesize у JS. Клієнтські обмеження обходяться за хвилину через консоль браузера. Серверний фільтр, єдиний реальний захист.

Друге. Зберігайте завантажені файли за межами document root або в папці з вимкненим виконанням скриптів. Наприклад, структура:

1/public_html ← document root ( index.php )
2/uploads ← папка с загруженными файлами (вне web-доступа)

Тоді пряме посилання на файл не спрацює, браузер віддає файл лише через PHP-скрипт-посередник, який перевіряє права доступу.

Третє. Генеруйте унікальні імена файлів на сервері. Не довіряйте імені, яке надіслав клієнт: воно може містити ../, нульові байти або спецсимволи. basename() + time() + випадковий рядок, мінімальний рівень.

Четверте. Перевіряйте вміст файлу, а не лише розширення. Зловмисник може перейменувати shell.php на photo.jpg і обійти фільтр за pathinfo(). Надійний спосіб: визначити реальний MIME-тип через finfo_file() (вбудований PHP-модуль Fileinfo) і звірити з білим списком. Для зображень додатково перевірте, що getimagesize() повертає валідні розміри — це відсіє биті файли та замасковані скрипти. На високонавантажених проєктах варто винести завантаження в окремий мікросервіс за реверс-проксі, який приймає потік, сканує антивірусом (наприклад, ClamAV) і лише потім віддає основному застосунку.

Коротке демо-відео вище показує весь процес у дії: HTML-розмітка, PHP-обробник і результат у браузері за три хвилини.

⁉️🤔 Часті запитання

Dropzone.js працює без jQuery?

Так, бібліотека повністю незалежна від jQuery. Починаючи з версії 5.x, усі залежності видалено, див. розділ Installation на dropzone.dev. Водночас є окрема jQuery-обгортка для тих, хто звик до $('.dropzone').dropzone(), вона лежить у тому самому npm-пакеті, шлях dist/min/dropzone-jquery.min.js.

Як змінити текст помилки, коли файл завеликий?

Використовуйте опцію dictFileTooBig. Приклад: dictFileTooBig: 'Файл слишком большой. Максимальный размер, {{maxFilesize}} МБ'. Шаблон {{maxFilesize}} автоматично підставить значення з вашої конфігурації. Повний перелік dict-ключів для локалізації є в документації.

Чи можна завантажувати файли частинами для великих обсягів?

Так, у Dropzone v5 є вбудована підтримка чанкового завантаження через опції chunking: true, chunkSize (у байтах) і forceChunking. Сервер при цьому повинен уміти збирати чанки: приймати кожен шматок із заголовками dzchunkindex і dztotalchunkcount, зберігати тимчасово та склеювати після отримання останнього. Для PHP готовий приклад збирання чанків є в репозиторії Dropzone.

Як видалити прев’ю файлу після успішного завантаження?

Викличте myDropzone.removeFile(file) в обробнику події success. Файл зникне з інтерфейсу, але на сервері залишиться. Якщо потрібно видалити і з сервера, додайте AJAX-запит у той самий обробник перед removeFile.

Dropzone сумісний із WordPress?

Так, бібліотеку можна підключити через wp_enqueue_script() у темі або плагіні. Типовий сценарій для WordPress: заміна стандартного завантажувача медіафайлів на користувацькій адмін-сторінці або на фронтенд-формі. Потрібно лише вказати коректний URL обробника, зазвичай admin_url('admin-ajax.php') із зареєстрованим AJAX-екшеном.

Чи варто брати Dropzone.js під ваш проєкт

Якщо вам потрібне завантаження файлів перетягуванням «тут і зараз», Dropzone.js закриває задачу швидше, ніж будь-який самописний код. П’ять причин, чому бібліотека залишається актуальною у 2026 році:

  • Жодних залежностей. Ні jQuery, ні Bootstrap, ні React. Підключили один JS-файл, і працює.
  • Кросбраузерність. Підтримує браузери аж до IE11, gracefully degradable без JavaScript.
  • Готова візуалізація. Прев’ю зображень, прогрес-бари, іконки успіху/помилки, з коробки, без CSS-верстання.
  • Документація. Актуальне GitBook та активний репозиторій на GitHub (1 700+ зірок на момент 2026 року).
  • Гнучкість. Від простого ресайзу зображень перед надсиланням до чанкового завантаження гігабайтних файлів, усе налаштовується через конфіг.

Коли Dropzone не найкращий вибір: якщо ви вже використовуєте React/Vue і хочете нативний компонент без DOM-маніпуляцій ззовні. В екосистемі React є react-dropzone, у Vue, vue-dropzone. Але для чистого JavaScript, jQuery-проєктів і WordPress-сайтів Dropzone.js — це перевірений інструмент, який не підведе.

Практичний приклад інтеграції. Один із типових сценаріїв на WordPress-сайті: сторінка «Завантажити документи» в особистому кабінеті клієнта. Користувач перетягує скани паспорта, договору та фото об’єкта. Dropzone підключається через wp_enqueue_script() у functions.php теми, обробником слугує кастомний AJAX-екшен, зареєстрований через wp_ajax_nopriv_. Кожен успішно завантажений файл записується до медіабібліотеки через wp_insert_attachment(), а його ID зберігається в user meta. Весь фронтенд-код уміщається в 30 рядків, серверна частина, у 50. Для порівняння: самописний drag-and-drop із тими самими можливостями зайняв би 400-600 рядків JavaScript і 2-3 дні розробки.

Щодо альтернатив: Uppy (від творців Transloadit) пропонує модульну архітектуру з плагінами для React, Svelte та завантаження в S3, але потребує більше залежностей і налаштування. Fine Uploader більше не підтримується з 2018 року, форки живуть, але без гарантій безпеки. Dropzone.js виграє балансом «можливості на одиницю складності»: один файл, мінімум конфігурації, результат видно через п’ять хвилин після підключення.

Кілька додаткових можливостей, які варто знати перед стартом. Dropzone надає повний цикл подій: addedfile, thumbnail, uploadprogress, complete і queuecomplete. Остання особливо корисна: вона спрацьовує, коли всі файли з черги оброблені, і ви можете показати користувачеві підсумкове повідомлення або перенаправити на іншу сторінку. Для мережевих збоїв є вбудований retry: у разі помилки завантаження Dropzone показує кнопку «Повторити» поруч із прев’ю файлу, повторне надсилання йде через той самий обробник без дублювання коду. Інтерфейс повністю локалізується через словник dict-опцій: dictCancelUpload, dictRemoveFile, dictMaxFilesExceeded і ще два десятки ключів, підтримка української мови робиться за п’ять хвилин копіюванням об’єкта з документації. Бібліотека важить 28 КБ у стисненому вигляді (gzip), що додає менш ніж 0,1 секунди до завантаження сторінки на мобільному 4G. Усі ці властивості роблять Dropzone.js стандартом де-факто для drag-and-drop завантаження в проєктах без фреймворків: мільйон завантажень npm на тиждень за даними на початок 2026 року, використання в адмінках WordPress, Laravel і Symfony.