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, RU-текст, который видит пользователь в пустой зоне загрузки.

Ключ 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-доступа)

Тогда прямой URL к файлу не сработает, браузер отдаёт файл только через 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.