HTML5: загрузка файлов с помощью Drag & Drop. Красивая AJAX форма для загрузки файлов Загрузка изображения drag and drop

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

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

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

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

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

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

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

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

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

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

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

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

    Dropzone.options.myDropzone = { init: function() { thisDropzone = this; $.get("upload.php", function(data) { $.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); }); }); } };

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

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

    Приветствую всех! В этой статье хочу рассказать о нескольких своих экспериментах с HTML5. Начну издалека. Всем нам периодически приходится работать с различными web интерфейсами и часто возникает ощущение, что эта работа могла бы быть организована более эффективно.

    Возможно, в каких-то случаях виноваты разработчики сервиса, но часто проблема заключается в ограничениях, которые накладывают браузеры. Рассмотрим загрузку файлов на сервер. В большинстве случаев вам предложат стандартное поле с кнопкой выбора файла с вашего компьютера и/или поле, в котором можно указать URL файла, размещенного где-нибудь в Сети.

    Загрузку файлов с локального компьютера трогать пока не будем, я планирую опубликовать отдельный пост на эту тему, разберем загрузку с удалённого сервера.

    Проблемы начинаются с первого же шага. Даже если вы четко понимаете, где искать URL и хорошо умеете пользоваться инструментами вроде firebug, то всё равно потребуется несколько кликов мышкой чтобы получить нужный адрес. Было бы гораздо удобнее просто перетянуть нужную картинку из одного окна браузера в другое.

    Пример реализации такого интерфейса я покажу в этой статье. Если хотите, можете посмотреть, как он работает на демонстрационной страничке или .

    Обратите внимание! Данный пример работает только в браузере Google Chrome. По-идее, поддержка всех необходимых технологий есть в Firefox и Safari, но с ними я пока не разбирался. В качестве объектов для «перетягивания» я брал в основном картинки с википедии. Было замечено несколько проблем связанных с не латинскими символами в URL картинок, но чтобы не перегружать пример проверками и преобразованиями я их оставил как есть.

    Принцип работы

    Стандарт HTML5 предусматривает поддержку «перетягивания» объектов страницы (Drag and Drop). Кстати, пример простейшей реализации D&D я уже показывал – Drag & Drop с использованием HTML5 . И, кроме того, есть довольно много JavaScript библиотек, реализующих поддержку D&D.

    Но тут важно понимать, что если необходимо «перетягивать» картинки со сторонних ресурсов, то использовать библиотеки не получится. Т.к. вы не сможете добавить свой JS код на чужую страницу. А для того, чтобы загрузить картинку, нам нужно получить её URL, т.е. браузер должен вместе с перетягиваемым объектом передавать и его параметры (например, атрибут src картинки или весь тег img).

    В этом случае мы можем создать на своей странице «приёмник» картинок. Это будет обычный div которому назначен обработчик события drop. Если пользователь «сбросит» картинку над этим div"ом, то будет вызван обработчик и в первом параметре он получит объект, содержащий информацию о перетягиваемой картинке.

    Реализация

    Начнём со страницы нашего приложения.

    Images Upload


    На ней размещены два блока: images – здесь будем показывать загруженные изображения и img_target – на этот блок нужно перетягивать картинки. Внизу страницы подключаем библиотеку jQuery и скрипт main.js, который будет отправлять информацию о перетянутых изображениях на сервер.

    Рассмотрим main.js
    $(function() {
    $("#img_target")
    .bind("dragenter", function(event) {
    $(this).addClass("drop_here");
    return false;
    })
    .bind("dragleave", function(event) {

    return false;
    })
    .bind("dragover", function(event) {
    return false;
    })
    .bind("drop", function(event) {
    $(this).removeClass("drop_here");
    var srcRegex = /src=\"([^\s]+)\"/ig;
    var data = event.originalEvent.dataTransfer.getData("text/html");
    var img_data = srcRegex.exec(data);
    $.post("upload.php", {"file_url":img_data}, function(res) {
    var response = eval("(" + res + ")");
    $("#images").append($(""));
    });
    return true;
    });
    });
    Здесь мы назначаем обработчики событиям dragenter, dragleave и dragover. Все они должны просто возвращать false и, чтобы как-то проинформировать пользователя о том, что можно «сбрасывать» картинку, в обработчике dragenter устанавливаем CSS класс drop_here для блока-приёмника. Основная часть работы выполняется в обработчике события drop. При возникновении этого события мы читаем информацию о «сброшенном» объекте и «вырезаем» значение атрибута src, т.е. URL картинки. Информация передается в объекте event.originalEvent.dataTransfer.

    Затем формируем обычный AJAX запрос и в качестве параметра передаём ему найденный URL. Серверный скрипт (upload.php) получит URL изображения на удалённом сервере и загрузит его. А в ответе на AJAX запрос он отправит новый URL загруженной картинки. В свою очередь, обработчик AJAX-запроса создаст тег img и вставит его в блок images. Таким образом, загруженные картинки будут появляться над полем загрузки.

    Рассмотрим upload.php

    Принцип работы следующий. Читаем URL картинки и пытаемся её загрузить. Если картинка загружена, сохраняем её в папку upload. Получение картинки с удалённого сервера осуществляется с помощью функций fread. Файл читаем блоками по 1кБ. Такой подход позволяет прервать загрузку файла, если его размер превышает заданный предел (в данном случае 300кБ).

    После загрузки файла формируем для него URL и отправляем браузеру в формате JSON. Как видите, реализовать такой загрузчик несложно. И пользоваться им достаточно удобно. Естественно, основным недостатком является поддержка HTML5 браузерами, точнее её отсутствие Тем не менее, если вы создаёте интерфейс для сотрудников какой-нибудь компании, и можете оговорить тип браузера, то HTML5 вполне можно использовать.

    Предоставить возможность пользователю загружать файлы на сервер перетаскивая их например, с рабочего стола. Причем чтобы была возможность перетащить сразу несколько файлов.

    Решение

    Как видно из примера выше, файлы отправляются на сервер сразу же после выбора. Отправим их по событию:

    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("");

    и меняем на:

    Var form = qq.toElement("");

    This markup doesn"t have anything specifically to do with drag and drop. It"s just a normal, functional , albeit with some extra HTML elements for potential states.

    Choose a file or drag it here. Upload Done! Error! .

    We"ll hide those states until we need them:

    Box__dragndrop, .box__uploading, .box__success, .box__error { display: none; }

    A little explanation:

    • Regarding states: .box__uploading element will be visible during the Ajax process of file upload (and the others will still be hidden). Then .box__success or .box__error will be shown depending on what happens.
    • input and label are the functional parts of the form. I wrote about styling these together in my post about customizing file inputs . In that post I also described the purpose of attribute. The input and label also serve as an alternative for selecting files in the standard way (or the only way if drag and drop isn"t supported).
    • .box__dragndrop will be shown if a browser supports drag and drop file upload functionality.
    Feature detection

    We can"t 100% rely on browsers supporting drag and drop. We should provide a fallback solution. And so: feature detection . Drag & drop file upload relies on a number of different JavaScript API"s, so we"ll need to check on all of them.

    Подготовили: Евгений Рыжков и Егор Скорняков Дата публикации: 12.06.2011

    Задача

    Предоставить возможность пользователю загружать файлы на сервер перетаскивая их например, с рабочего стола. Причем чтобы была возможность перетащить сразу несколько файлов.

    Решение

    Смотрим демо пример . Пример можно забрать архивом . Проверено:

    • 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 в несжатом виде)
    Быстрый старт

    Подключаем скрипты, а в форму добавляет type =file с . Если браузер не поддерживает необходимый набор API, пользователь сможет загрузить фото «по старинке». Чтобы у него была возможность добавить несколько фото, динамически добавим кнопку «+», которая будет добавлять поля input type=file. Для этих целей в id поля присутствует 0, чтобы проще было организовать правильные имена добавленных полей.

    ...

    Для браузеров, которые поддерживают Dnd и File API можно поля type=file вообще скрыть или удалить.

    Как это работает

    Если не вдаваться особо в детали, тогда принцип работы можно отобразить в виде подобной схемы:

  • (DnD API) все начинается когда пользователь отпускает зажатую кнопку мыши — срабатывает событие drop;
  • (DnD API) получаем объект DataTransfer от события drop;
  • (File API) вызывая DataTransfer.files получаем FileList — список файлов, которые пользователь перетащил в область загрузки;
  • (File API) перебирая все файлы читаем их содержимое с помощью объекта FileReader;
  • (File API) вызывая FileReader.readAsDataURL(../../../collect/js-plugins/ui/file) каждый раз, когда очередной файл удачно прочитан, формируем data URL объект. Когда он полностью будет сформирован произойдет событие onloadend объекта FileReader;
  • когда мы получили объект data:URL, мы можем подставить эти данные в src и отобразить , а так же отправить данные в двоичном виде на сервер;
  • (XMLHttpRequest 2) асинхронно отправляем данные, а с помощью новых фишек второй версии протокола XMLHttpRequest получаем данные о состоянии загрузки (событие progress), что позволяет информировать пользователя.
  • Fine Uploader Plugin

    update: 18.09.12 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. На реальном сервере скорее всего этот пункт не потребуется.

      • если тестируем на веб сервере, то ставим ей права 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);

    Подключаем скрипт плагина и стили:

    Please enable JavaScript to use file uploader.

    JS-инициализация:

    Window.onload = function(){ var uploader = new qq.FileUploader({ element: document.getElementById("file-uploader1"), action: "php/upload.php" // путь к серверной части плагина }); };

    Поделиться