Возможно, в каких-то случаях виноваты разработчики сервиса, но часто проблема заключается в ограничениях, которые накладывают браузеры. Рассмотрим загрузку файлов на сервер.
В большинстве случаев вам предложат стандартное поле с кнопкой выбора файла с вашего компьютера и/или поле, в котором можно указать 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 вполне можно использовать.
Успехов!
Ссылки по теме