HTML5: загрузка файлов с помощью Drag-and-drop
Приветствую всех! В этой статье хочу рассказать о нескольких своих экспериментах с 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'ом, то будет вызван обработчик и в первом параметре он получит объект, содержащий информацию о перетягиваемой картинке.
Дальше всё достаточно просто. Если мы получили нужный URL, то можно отправить AJAX-запрос серверному скрипту, который выполнит загрузку файла.
Реализация
Начнём со страницы нашего приложения.
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Images Upload</title> <link rel="stylesheet" type="text/css" href="styles.css" /> </head> <body> <div id="images"></div> <div id="img_target"></div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> <script src="main.js"></script> </body> </html>
На ней размещены два блока: 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) { $(this).removeClass('drop_here'); 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[1]}, function(res) { var response = eval('(' + res + ')'); $('#images').append($('<img src="' + response.file_url + '" />')); }); 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
<?php define('BASE_URL', 'http://localhost/tests/images-upload/'); function upload_from_url($file_url) { $url_segments = explode('/', $file_url); $file_name = urldecode(end($url_segments)); if (false !== $file_name) { $file_name_parts = explode('.', $file_name); if (in_array(strtolower(end($file_name_parts)), array('jpeg','jpg','png','gif'))) { $destination=fopen("upload/".$file_name,"w"); $source=fopen($file_url,"r"); $maxsize=300*1024; $length=0; while (($a=fread($source,1024))&&($length<$maxsize)) { $length=$length+1024; fwrite($destination,$a); } fclose($source); fclose($destination); } } $new_file_url = BASE_URL.'upload/'.$file_name; return $new_file_url; } $res = array('err' => 'Не указан URL файла'); if (isset($_POST['file_url'])) { $new_url = upload_from_url($_POST['file_url']); $res = array('file_url' => $new_url); } echo json_encode($res); ?>
Принцип работы следующий. Читаем URL картинки и пытаемся её загрузить. Если картинка загружена, сохраняем её в папку upload. Получение картинки с удалённого сервера осуществляется с помощью функций fread. Файл читаем блоками по 1кБ. Такой подход позволяет прервать загрузку файла, если его размер превышает заданный предел (в данном случае 300кБ).
После загрузки файла формируем для него URL и отправляем браузеру в формате JSON. Как видите, реализовать такой загрузчик несложно. И пользоваться им достаточно удобно. Естественно, основным недостатком является поддержка HTML5 браузерами, точнее её отсутствие
Тем не менее, если вы создаёте интерфейс для сотрудников какой-нибудь компании, и можете оговорить тип браузера, то HTML5 вполне можно использовать.
Успехов!
Written by: Владимир Стаценко
WWW: http://www.simplecoding.org/html5-zagruzka-fajlov-s-pomoshhyu-drag-drop.html
Date: 23.10.2011
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
- 1493 просмотра



Комментарии
2 комментария(ев)Дата: ВС, 23/10/2011 - 20:39
Я не вчитывался ни в эту статью ни в прошлую, но по-моему эта тема там освещалась.
Знакомимся с HTML5 на практике
Спайдер писал.
Дата: ВС, 23/10/2011 - 20:59
Неа, это не повтор. Подходы разные.