Drag-n-Drop загрузка файлов
Задача
Предоставить возможность пользователю загружать файлы на сервер перетаскивая их например, с рабочего стола. Причем чтобы была возможность перетащить сразу несколько файлов.
Решение
Смотрим демо пример. Пример можно . Проверено:
- IE 6-9
- Firefox 3.6-4
- Opera 11.1
- Chrome
- Safari 5
Обращу внимание, что в данном случае проверено != работает:
- IE включая 9-ю версию не поддерживает File API (старая реализация);
- Firefox 3.6+ поддерживает все, что нужно. Для более старых версий — старая реализация;
- Opera 11.1 поддерживает File API, но не поддерживает DnD;
- Chrome, начиная с 10-й версии, поддерживает все, что нужно;
- Safari поддерживает все что нужно с 6-й версии.
Какой толк от этого в таком случае? Пользователи нормальных браузеров получают более удобные сайты.
Что качать:
- (12Kb в несжатом виде)
Быстрый старт
Подключаем скрипты, а в форму добавляет input type=file с id. Если браузер не поддерживает необходимый набор API, пользователь сможет загрузить фото «по старинке». Чтобы у него была возможность добавить несколько фото, динамически добавим кнопку «+», которая будет добавлять поля input type=file. Для этих целей в id поля присутствует 0, чтобы проще было организовать правильные имена добавленных полей.
<script src="path-to/jquery.min.js"></script> <script src="path-tp/jquery.client.js" charset="utf-8"></script> ... <input type="file" id="fileUpload0" multiple="true" size="60">
Для браузеров, которые поддерживают Dnd и File API можно поля type=file вообще скрыть или удалить.
Как это работает
Если не вдаваться особо в детали, тогда принцип работы можно отобразить в виде подобной схемы:
- (DnD API) все начинается когда пользователь отпускает зажатую кнопку мыши — срабатывает событие drop;
- (DnD API) получаем объект DataTransfer от события drop;
- (File API) вызывая DataTransfer.files получаем FileList — список файлов, которые пользователь перетащил в область загрузки;
- (File API) перебирая все файлы читаем их содержимое с помощью объекта FileReader;
- (File API) вызывая FileReader.readAsDataURL(file) каждый раз, когда очередной файл удачно прочитан, формируем data URL объект. Когда он полностью будет сформирован произойдет событие onloadend объекта FileReader;
- когда мы получили объект data:URL, мы можем подставить эти данные в src и отобразить изображение, а так же отправить данные в двоичном виде на сервер;
- (XMLHttpRequest 2) асинхронно отправляем данные, а с помощью новых фишек второй версии протокола XMLHttpRequest получаем данные о состоянии загрузки (событие progress), что позволяет информировать пользователя.
Fine Uploader Plugin
update: by Андрей Косяк.
Довольно удобный js-плагин по заливке файлов на сервер. Написан на чистом JS. Состоит из серверной части ( на нескольких языках ) и клиентской ( JS и CSS ).
НЕ использует флеш и какие-либо фреймворки.
Fineuploader использует XMLHttpRequest объект для передачи файлов с прогрессбаром для современных браузеров, а для всякого треша используется способ со старым добрым iframe-ом.
Знакомимся:
- Проект на GitHub
- Родная демка
- Документация ( на англ.)
Проверено:
- IE 7-9
- Firefox 3.6+
- Opera 10.6+
- Chrome
- Safari 4+
Быстрый старт
Работоспособность плагина нужно проверять исключительно с сервера ( локальный подойдет ). В примере буду использовать серверную часть на PHP.
Перед первым стартом нужно подготовить почву:
-
На локальном сервере первое, что попросит скрипт, это увеличить значения параметров post_max_size и upload_max_filesize. Открываем файл php.ini находим эти параметры и ставим значения >= 10M. На реальном сервере скорее всего этот пункт не потребуется.
-
Нужно создать папку uploads ( далее будем считать, что она создана в корне сайта ) и :
- если тестируем на веб сервере, то ставим ей права 777
- если тестируем на локальном, то в свойствах папки убираем галочку "только для чтения" ( может работать и без этого )
-
из папки /server плагина забираем файл php.php. В нем, в первом блоке комментариев написано, какие строки нужно извлечь из комментариев, чтобы инициализировать класс. Добавляем сразу после блока с комментарием:
// допустимые расширения файлов $allowedExtensions = array(); // максимальный размер файла $sizeLimit = 10 * 1024 * 1024; // инициализация класса $uploader = new qqFileUploader($allowedExtensions, $sizeLimit); // тут нужно указать путь к папке /uploads $result = $uploader->handleUpload("../uploads/"); // возврат ответа после сохранения файла echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
Подключаем скрипт плагина и стили:
<link rel="stylesheet" href="css/fileuploader.css"> <script src="js/fileuploader.js"></script>
HTML-код:
<div id="file-uploader"> <noscript> <p>Please enable JavaScript to use file uploader.</p> </noscript> </div>
JS-инициализация:
window.onload = function(){ var uploader = new qq.FileUploader({ element: document.getElementById('file-uploader1'), action: 'php/upload.php' // путь к серверной части плагина }); };
Как видно из примера выше, файлы отправляются на сервер сразу же после выбора. Отправим их по событию:
window.onload = function(){ var uploader = new qq.FileUploader({ autoUpload: false, element: document.getElementById('file-uploader'), action: 'php/upload.php' }); $( '#startUpload' ).on( 'click', function(){ uploader.uploadStoredFiles(); } ); };
В целом у плагина много опций и настроек, имеются колбеки. Все это описано тут. Fineuploader находится в постоянной разработке, поэтому рекомендую при привязке посещать репозиторий и брать свежую версию.
Стилизация
Плагин создает свою структуру на базе класса .qq-uploader, все элементы описаны в css файле fileuploader.css
На заметку
Если ослы упорно отказываются работать, открываем скрипт, ищем там строку:
var form = qq.toElement('<form method="' + protocol + '" enctype="multipart/form-data"></form>');
и меняем на:
var form = qq.toElement('<form method="' + protocol + '" enctype="application/octet-stream"></form>');
Материалы
- HTML5 File API: множественная загрузка файлов на сервер
- HTML5 Drag and Drop Upload and File API Tutorial