Загрузка файлов, наверное, самая сложная тема при работе с формами в веб-приложениях. Стандартный элемент формы <input> для загрузки файла, его внешний вид, и тем более функционал давно не устраивают разработчиков.
Раньше были очень популярны flash-формы. Они избавляли сайт от недостатков стандартного загрузчика, но, в последнее время, в связи с отказом от продолжения развития flash-технологии и отсутствия поддержки её на android платформе, это решение теряет популярность.
Сейчас появились качественные js-script-ы, которые помогают решить задачу. Об одном из них я и расскажу дальше.
DropZone.js — drag & drop загрузчик файлов с пред-просмотром картинок
DropZone позволяет превратить в загрузчик файлов любой элемент документа, в том числе и не являющийся частью контейнера form.
Внешне зона, куда сбрасываются файлы выглядит вот так:
Её можно настроить на ваш вкус, используя CSS и инициализацию объекта. Файловый диалог откроется в том числе и по клику.
Если файлы не загрузились по каким либо причинам, то они отмечается крестом, а в подсказке выводится сообщение с расшифровкой ошибки.
Как работает DropZone?
Скрипт отправляет файлы по ajax на сервер сразу, не дожидаясь отправки всех данных формы. Вы должны сами решить, что с ними делать. DropZone обеспечивает только фронт-энд составляющую.
Вообще, скрипт вырван из контекста формы, используя у формы только параметр action, чтобы взять url для отправки данных по ajax.
Инициализация
Подключаем файлы скрипта и стили
1 2 |
<script src="path/to/dropzone.min.js"></script> <link rel="stylesheet" href="path/to/dropzone.min.css" type="text/css" /> |
Возможно, вы захотите работать с dropzone как с плагином jQuery. Тогда добавьте ещё один небольшой файл вот из этого проекта — jquery.dropzone.
1 |
<script src="path/to/jquery.dropzone.min.js"></script> |
Скрипт по-умолчанию обрабатывает контейнеры, отмеченные классом .dropzone. Но чаще всего инициализацию проводят программно, чтобы настроить работу так, как требует ситуация.
Пример инициализации контейнера по id:
1 |
new Dropzone("#IDhtmlcont", { url: "/file/post"}); |
Можно передать все необходимые опции ещё до инициализации — через глобальный объект Dropzone.options.
Пример такой инициализации:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//для контейнера с id #IDhtmlcont - Dropzone.options.IDhtmlcont = { paramName: "file", // имя переменной, используемой для передачи файлов maxFilesize: 2, // лимит размера файла в МБ parallelUploads: 1, //кол-во параллельных обращений к серверу maxFiles: 10, //макс. число файлов в данном контейнере accept: function(file, done) { //произвольная функция проверки загружаемых файлов if (file.type == "image/png") { //сообщение без ошибки, если файл забракован done("I don`t accept PNGs."); } //чтобы файл был принят, нужно вызвать done без параметров else { done(); } } }; |
Событие accept возникает уже после всех проверок, в том числе и на тип файла, если он задан как параметр, к примеру, вот так:
1 |
acceptedFiles: 'image/png, image/jpeg', |
В accept вы можете добавить финальные штрихи к проверке, уже зная данные о файле.
Отправка файлов в dropzone
При минимальных настройках, вы можете понять назначение отправленных файлов только по адресу скрипта-обработчика. Этого мало, чтобы организовать полноценную работу. Потому следующий шаг заключается в том, чтобы сопроводить отправку файлов по ajax дополнительными маркерами, данными.
Так как я много пишу на Drupal, то обычно использую уникальный код формы, который подцепляется drupal form api к каждой форме — form_build_id. У вас это может быть какой то другой маркер, в зависимости от CMS или framework, который вы используете.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Dropzone.options.IDhtmlcont = { ... //можно включить в обработчик init init: function() { var formbuildid = $('#formID input[name="form_build_id"]').get(0).value; this.on('sending', function (file, xhr, formData) { formData.set('form_build_id', formbuildid); }); }, ... //или как самостоятельный параметр в настройках sending: function(file, xhr, formData) { var formbuildid = $('#formID input[name="form_build_id"]').get(0).value; formData.set('form_build_id', formbuildid); }, }; |
Без этого будет сложно понять кто и зачем передавал данные. :)
Организация работы dropzone со стороны сервера
Типично возникает три подзадачи:
- Прием данных от dropzone;
- Связывание полученных из dropzone файлов с данными формы;
- Инициализация списка файлов уже находящихся на сервере для отображения в контейнере .dropzone.
Прием данных от dropzone на сервере
По указанному в настройках URL скрипт направляет файлы. Если вы настроили отправку по одному файлу за раз, то получите примерно вот такой массив $_FILES на входе:
1 2 3 4 5 6 7 8 9 10 |
Array ( //имя переменной, которую вы выбрали для передачи данных [file] => Array ( [name] => 1.jpg [type] => image/jpeg [tmp_name] => \tmp\php3FAF.tmp [error] => 0 [size] => 137528 ) ) |
Все проверки на кол-во, размеры и типы на сервере придется продублировать.
Файлы нужно будет где то временно сохранить, до тех пор пока не придут данные формы, с которыми файлы ассоциированы логикой программы.
Если файлы так и не будут востребованы, нужно предусмотреть механизм их удаления через какое то время.
Инициализация списка файлов
Эта задача возникает при работе с формой по ajax и сложных взаимодействиях пользователя с веб-приложением.
По этому поводу есть хорошая статья, от которой я отталкивался в своей работе. Рекомендую ознакомиться — dropzonejs-php-how-to-display-existing-files-on-server.
Здравствуйте. Подскажите пожалуйста как добавить описание файла после загрузки?
Для начала проверьте настройки поля — включите соответствующие meta-поля. После сохранения ноды, их можно будет заполнить в редакторе.
Спасибо!!