Приветствую всех!
В этой статье хочу рассказать о нескольких своих экспериментах с 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 картинки (строки 16-18). Информация передается в объекте event.originalEvent.dataTransfer (строка 17).
Затем формируем обычный 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 картинки и пытаемся её загрузить (строки 29-32).
Если картинка загружена, сохраняем её в папку upload
. Получение картинки с удалённого сервера осуществляется с помощью функций fread
. Файл читаем блоками по 1кБ (строки 15-18). Такой подход позволяет прервать загрузку файла, если его размер превышает заданный предел (в данном случае 300кБ).
После загрузки файла формируем для него URL и отправляем браузеру в формате JSON.
Как видите, реализовать такой загрузчик несложно. И пользоваться им достаточно удобно. Естественно, основным недостатком является поддержка HTML5 браузерами, точнее её отсутствие 😉
Тем не менее, если вы создаёте интерфейс для сотрудников какой-нибудь компании, и можете оговорить тип браузера, то HTML5 вполне можно использовать.
Успехов!
Интересно почитать.
Фотокнига — фантастический сюрприз для любимого мужчины. Попробуйте сами!
Правильно подготовим 3-ндфл при покупке квартиры за 2011 год, дадим инструкции для получения вычета
Нужно распарсить сайт? Интересный пример как написан парсер на php. Можно даже скачать скрипт парсера.