SWFUpload + jQuery: очередная имплементация файлового загрузчика

SWFUpload + jQuery: очередная имплементация файлового загрузчика

На тему файловых загрузчиков я уже написал три статьи: раз, два, три. Возможно внешний вид файлового загрузчика - моя личная маниакальная одержимость и мне надо к врачу, или же я просто делюсь своими стремлениями к идеалу красоты загрузчика. Искусство мыть слона в действии.

На этот раз будем будем использовать js-библиотеку SWFUpload и jQuery.

Для начала поясню, кто такой SWFUpload и зачем он может быть нужен.

Итак, SWFUpload - это js-библиотека, обертка для флэш-объекта, который позволяет загружать файлы. Только в отличие от обычного файл-аплода, флэш радует нас возможностью выбирать несколько файлов, получать информацию о процессе загрузки и на клиенте оценивать размер и формат выбранных файлов.

SWFUpload дает полную свободу разработчику в имплементации внешнего вида загрузчика - свобода, которая может быть ограничена разве что знанием HTML+CSS.

Собственно, этой свободой я и решил воспользоваться, когда моя мысль добрела до идеи.

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

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

Не мешает, всегда видно. Красиво и удобно.

Внешний вид того, что будем делать мы:

Лоутек:

Хайтек:

HTML:

<div id="Buttons">
<span id="UploadPhotos">
<input type="button" id="Progress" /><i id="fAddPhotos"></i><input type="button"
id="AddPhotos" value="Upload Photos" />
</span>
</div> <script type="text/javascript">
window.onload = function() { BindSWFUpload();} </script>

 CSS:

 #Buttons {
padding: 0;
position: relative;
color: #666666;
width: 200px;
text-align: left;
margin: 200px auto 0;
}
#UploadResult{
padding: 0 10px;
}
input#AddPhotos {
}
#Buttons span {
line-height: 32px;
}
#Buttons input, .niceButton {
border-style: none;
border-color: inherit;
border-width: 0;
background: url('../images/btn.png') no-repeat 0 -32px;
color: #666666;
font-size: 14px;
height: 32px;
width: 115px;
cursor: pointer;
outline: none;
text-decoration: none;
line-height: 32px;
}
#Buttons input:hover, #Buttons input.hover, .niceButton:hover {
background-position: 0 0;
color: #333;
outline: 0 none;
}

#Buttons object {
outline: none;
position: absolute;
}
input#Progress
{
background: url('../images/progress.png') no-repeat 0 0px;
width: 115px;
height: 32px;
position: absolute;
width: 0;
padding: 0;
}

JS:

Метод, инициирующий наш флэш-загрузчик BindSWFUpload. В нем мы задаем настройки загрузчика - количество допустимых файлов, дозволенные форматы, ограничение на размер и объявляем хендлеры для разных этапов процесса загрузки.

 var swfuPhotos;
function BindSWFUpload() {
var swfuPhotosSettings = {
file_dialog_complete_handler: photos_fileDialogComplete,
upload_progress_handler: photos_uploadProgress,
upload_success_handler: photos_uploadSuccess,
upload_complete_handler: photos_uploadComplete,
swfupload_loaded_handler: swfuploadLoaded,
file_queue_error_handler: photos_fileQueueError,
file_size_limit: "2 MB",
file_types: "*.jpg;*.png",
file_types_description: "JPG, PNG images",
file_upload_limit: "5",
button_placeholder_id: "fAddPhotos"
}

var defaultSettings = {
flash_url: "files/swf/swfupload.swf",
upload_url: "upload.php",
post_params: {
"ASPSESSID": ASPSESSID
},

button_width: 115,
button_height: 32,
button_image_url: "files/images/white50.png",

button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
button_cursor: SWFUpload.CURSOR.HAND
}

swfuPhotos = new SWFUpload($.extend(swfuPhotosSettings, defaultSettings));
}

Ну а теперь подробнее о самом процессе. Рассмотрим две функции - uploadProgress и uploadSuccess. Первый из них отслеживает состояние загрузки файлов - у него два параметра: файл и объем загруженных байт. Несложной функцией мы преобразуем этот объем байт в часть индикатора загрузки, который, в свою очередь, разбит на n частей, где n - количество загружаемых файлов.

var Count = 0;
var UploadedFiles = 0;
function photos_uploadProgress(file, bytesLoaded) {
try {
var pw = 115;
var w = Math.ceil(pw * (UploadedFiles / Count + (bytesLoaded / (file.size * Count))));
$('#Progress').stop().animate({ width: w });
} catch (ex) {
}
}
function photos_uploadSuccess(file, serverData) {
try {
UploadedFiles++;
} catch (ex) {

}
}

 В остальных хэндлерах нету ничего особенного, поэтому сюда их копипастить не буду.

В реальном проекте, безусловно, стоит сделать прелоад картинок, реализовать обработку всех ошибок и прочее. Ну а для демонстрации достаточно и этого.

Демо Скачать

Понравилась статья? Ретвит!

Расскажите друзьям

Оцените статью:
  • 1
  • 2
  • 3
  • 4
  • 5

Комментарии — 62

Ruby Roid
Спасибо, статья понравилась, уже думаю, где бы это применить.
Саша Кириллов
Жень, спасибо.

Предыдущая статья про стилизацию файл-инпутов мне очень помогла в одном из проектов. Даже я со своими дизайнерскими мозгами смог применить описанный метод. А нынче у нас даже с индикацией загрузки. Клево!

Два дурацких вопроса:
— Работает ли оно в Shiretoko 3.1 ИЕ6?
— Что происходит, если у пользователя не установлен флеш-плеер?
Димон
Это называется закон заподла в действии (((
За час до вашего поста Я закончил интеграция асинхронного загрузчика файлов с помощью "uploadify". Интегрировал Я его в CI-фреймворк.
Мучался Я с ним целый день(((.
Если бы на денек раньше выложили данный пост, то сэкономили мне кучу нервов и времени )))

Все равно спасибо за статью - будет время - обязательно прочитаю )))

#
Димон
Евгений
Саша, вопросы отнюдь не дурацкие.
1. В IE 6 работает
2. Если у пользователя не установлен флеш, то ничего не происходит. На такой случай надо делать другую имплементацию. Чтобы оставить внешний вид без изменений, я рекомендую Ajax Upload.

Димон, бывает. Зато, может быть, у вас появился интересный опыт. Или просто время зря потратили.
Так или иначе, я вас понимаю. Бывает подготовишь материал для статьи, чтобы на следующий день написать текст, но тут какой-то забугорный красавец постит чуть ли не то же самое, или очень похожее. Повторяться - некрасиво. А время потрачено. Такое, наверное, раз пять было.
Kykyryzo
Здорово, мне понравилось, хоть и я не долюбливаю флеш, но в том, что касается загрузки файлов, лучше ничего пока нет
Albanec
Большое спасибо, Евгений.
Анна из Одессы
Честно говоря, никогда так не делала. Просто не знала о такой возможности. Теперь попробую, спасибо!
Разработчик
Вот это отличное решение аплоада, из тех которые встречал. на jQuery. Без лишнего функционала легко и доступно. )
Skyman
ff 3.5.8 linux - анимация не работает. сразу показывает, что изображение прикреплено.
#
Skyman
Evgenij
Скайман, может он быстро загружается? Попробуйте файл покрупнее и количеством побольше.
Если не будет работать - посмотрите фаербагом что происходит с input id="Progress": его ширина должна увеличиваться от 0 до 115.
Skyman
Evgenij
Указал 5 изображений немалого размера. После этого несколько секунд была зарузка, но анимации не было. ПОтом показало сообщение , что данные переданы.
Т.е. все так же.
#
Skyman
Skyman
А смену инпута не замечено. Лишь вконце спан с айдишником UploadPhotos исчезает (display:none).
Кстати, а флешка сама процесор жрет при этом нехило. При этом лиса тормозит жутко и не отвечает на запросы юзера.
#
Skyman
Евгений
Подозреваю, что флэш для linux неполноценен.
В других браузерах такая же картина или проблема только с FF?
Skyman
Opera 10.10qt - то же самое
Ну не скажу, что на линуксе флеш идеален, хотя это адобовский компонент, но другие флешки работают. Скорее всего что-то в самом sfw'е.
#
Skyman
Влад
А где фыбрать каталог ?
#
Влад
Evgenij
На жестком диске
Влад
Evgenij
На жестком диске


остроумно
#
Влад
Evgenij
Каков вопрос, таков и ответ ;)
Максим
Залил на сервер, пытаюсь загрузить файл, пишет 1 image attached, а самого файла на сервере то нет, что нужно еще сделать?
#
Максим
Евгений
Максиим,
теперь файл (upload_url: "upload.php") должен принимать и обрабатывать файлы.
Если возникнут трудности, то на сайте загрузчика есть много рабочих примеров - посмотрите. Здесь я показал только часть, касающуюся оформления.
Максим
А как насчет имя переменной файла, в которой upload.php обращается к файлу, где ее указывать?
#
Максим
Evgenij
задается параметром file_post_name
http://demo.swfupload.org/Documentation/#settingsobject
ирина
Спасибо за статью.
У меня не срабатывало наведение на кнопку! Долго смотрела стили, а оказалось что я взяла jquery-1.4.1 и сней почему-то эффект наведения не работает, а с jquery-1.3.2 работает!
В чем проблема, как здесь с играл css и jquery?
#
ирина
Evgenij
Да, Ирина, есть такой косяк. Сам замечал, искал ответ, но не нашел.
Ирина
Спасибо за ответ! будет пока без этого эффекта... будет время покопаемся)))
#
Ирина
John
Евгений! Ваше решение шикарно!!
но возник вопрос!
подскажете, возможно ли на одной странице поставить более чем 1 кнопку для загрузки?
SWFupload позволяет это зделать, однако не могу понять как это сделать после Вашего апгрейда..

#
John  
John
сорри, упустил window.onload
в место него $(document).ready(function(){});
и соответственно в коде пронумеровать...

спасибо работает :)
#
John  
Valentin
А пример Ваш у меня только одного не работает или у всех? Пробовал уже пллагин: http://blogs.bigfish.tv/adam/2009/06/14/swfupload-jquery-plugin/ - не работает (оставил там коммент), хотя раньше работал ... Да даже на самом сайте разработчика - http://demo.swfupload.org/v220/eidemo/index.php - не работает ...
#
Valentin
Evgenij
Valentin, очевидно проблема у вас (возможно выключен js или не установлен(выключен) флэш.
Пример работает замечательно.
Valentin
Хм ... JS включен, флеш стоит последний. Проверял в FF, Chrome, Safari. Может я что-то не так делаю???

index.html

ASPSESSID = "ciftuemt43pxrh55jjdohm3o";
window.onload = function() { BindSWFUpload();}


script.js
function BindSWFUpload() {
var swfuPhotosSettings = {
............
file_post_name: 'uploadfile',
............

upload.php
$uploaddir = $_SERVER["DOCUMENT_ROOT"] . '/upload/';
$uploaddir = str_replace('//', '/', $uploaddir);
$file = $uploaddir . basename($_FILES['uploadfile']['name']);
$size = $_FILES['uploadfile']['size'];
if($size > 1048576)
{
echo "error file size > 1 MB";
unlink($_FILES['uploadfile']['tmp_name']);
exit;
}
if(move_uploaded_file($_FILES['uploadfile']['tmp_name'], $file))
{
echo "success";
}
else
{
echo "error ".$_FILES['uploadfile']['error']." --- ".$_FILES['uploadfile']['tmp_name']." %%% ".$file."($size)";
}

Здесь есть что-то неверное?

Спасибо за внимание.
#
Valentin
Valentin
Проверю - отпишусь.
#
Valentin
Владимир
Все как-то ленюсь спасибо авторам за сайт сказать, а между тем, это самое малое, что можно сделать. Большое спасибо за Ваш сайт, ребята! Читал далеко не все статьи у вас, но все что читал действительно качественный материал, а не вода. Заниматься дизайном как-то времени не хватает, да и фантазии (с этим уже смирился :) ) А требования конечно сам себе выдвигаешь строгие, изюминки вечно хочется. Вот у вас мыслями креативными заряжаюсь. Так держать! ))
#
Владимир
Valentin
Проверю - отпишусь.


Оказывается был глюк с plugin-container.exe ...

Авторам действительно огромное спасибо за их огромный труд в ликбезе, да и просто предоставлении познавательной инфы.

СПАСИБО!!!
#
Valentin
PuMi
Неудобно что эта кнопка заточена под надпись "Upload photo", если надпись будет побольше, то текст не будет помещаться в кнопку и и надо увеличивать изображения в фотошопе.
#
PuMi
Данил
Скрипт хороший, хотелось бы еще к нему прикрутить чтоб после загрузки рядом с названием фото была сама маленькая фоточка, которая загрузилась и окошко шде можно было написать текст фотки, как это можно реализовать?
#
Данил
Evgenij
В сам swfupload встроена такаая функциональность. Смотри документацию swfupload
=dAntaeuSb=
Заме4ательные статьи, постоянно захожу на ваш сайт :) Спасибо, прочитал все ваши материалы, особенно понравилось про iPhone, сделал таким образом прокрутку новостей на сайте :) Очень удобно. Но собственно, вопрос:
Есть ли шанс не внедряясь в структуру флеша сделать так, что бы в конце загрузки он через fade показал белый экран и воскликнул: "Загружено!" на том же белом фоне? (Текст это не проблема, но вот как моргание сделать?)
#
=dAntaeuSb=
Александо
Отлично! Спасибо большое! А можно вопрос, возможно глупый, сможет ли в данном способе пользователь обойти file_size_limit,file_types и file_upload_limit? Необходима ли повторная валидация на стороне сервера?
#
Александо
Zhendalf
Александро,
да, валидировать надо. Эти лимиты пользователь сможет переопределить если очень захочет.
Arconas
А есть ли возможность использовать не картинку для кнопки, а обычный input type button? Без placeholderid он просто не хочет работать.
Сергей
Спасибо за статью!
и сразу несколько вопросов:
1. Как вывести названия загруженных файлов списком и ссылки на них(для скачивания).
2. И как вывести ссылку на удаление уже загруженного файла.
Сергей
Еще один вопрос, каким шрифтом ты делал надпись на кнопке?
tester
Народ, подскажите, почему невозможно загружать с помощью этого загрузчика файлы больше 2 МБ. Несмотря на то, что file_size_limit : "100 MB".
#
tester
Zhendalf
Думаю вам стоит посмотреть настройки сервера, потому что с помощью этого загрузчика можно загружать очень большие файлы.
Chips
У меня стоит винда 7, в ней возникла слюдующая проблема: днный загрузчик, как и многие другие в независимости от размера файла, визуально как бы загружают файл за секунду т.е. полоса загрузки пробегает до конца моментально и дальше висит пока файл реально не загрузится. В чем может быть проблема?
#
Chips
Zhendalf
Chips, у меня аналогичная ситуация возникала, когда траффик шел через прокси. Например, я для тестирования использовал Фиддлер. Файл моментально попадал в фиддлер и индикатор загрузки сразу же подходил к концу.
Chips
ну тут дело не в прокси. в ХР работает нормально и локально и на сервере а вот в семерке нехочет
#
Chips
Zhendalf
Я пробовал и на XP (IIS 6) и на семерке (IIS 7).
На каком сервере происходит дело?
Chips
http://jazzkirov.ru/UploadButton/ попробуй
#
Chips
Zhendalf
Попробовал. Работает нормально.
Chips
У тебя семерка стоит?
#
Chips
Chips
Блин у других на семерке работает. Значит проблема чисто у меня!
#
Chips
Chips
Пытался сделать так чтобы информация о загруженом файле записалась в базу данных, но почему-то sql запросы в файлее upload.php неработают. В чем может быть причина?
#
Chips
Альфа
Как вывести в upload.php что-то а не только тупо загрузить файл??
#
Альфа
Alex
Как сделать чтобы после загрузки фоток не появлялось сообщение а переходило автоматом на какую нибудь страницу или обновляло эту?
#
Alex
Дмитрий
Приятный сайт у Вас :)
Подскажите, может ли этот аплоадер загружать не только изображения но и файлы другого типа? (*.rar, *.psd)? И если да, то как это реализовать?
Александр
Добрый день! в ie6 возникла проблема - в хэндлер uploadSuccess почему-то параметр serverData приходим пустым! Кто-нибудь сталкивался с подобным?
#
Александр
Дмитрий
Очень полезная статья. Я посмотрел, скачал пример и на его основе быстро создал пример под свою задачу и потом переписал на своё приложение =) СПС.
#
Дмитрий
john
подскажите как сделать чтоб работало на русскоязычном домене?
#
john
john
скрипт напрочь отказывается работать если домен состоит из: xn--80adxhks.xn--p1ai
есть где-то в файле swfupload.js всего-то строка которую надо поправить!!
помогите, прав ли я?
#
john
Иван
Как можно сделать, что бы после загрузки файлов можно было использовать еще раз загрузчик?
#
Иван

Новый комментарий

как выглядит какой тег
жирный текст <b>жирный текст</b>
курсивный тект <i>курсивный тект</i>
зачеркнутый текст <s>зачеркнутый текст</s>
подчеркнутый текст <u>подчеркнутый текст</u>
ссылка <a href="адрес">ссылка</a>
function foo() { ... }
<pre><code>function foo() { ... } </code></pre>
разрешенные теги или посмотреть как будет выглядеть
как выглядит какой тег
жирный текст <b>жирный текст</b>
курсивный тект <i>курсивный тект</i>
зачеркнутый текст <s>зачеркнутый текст</s>
подчеркнутый текст <u>подчеркнутый текст</u>
ссылка <a href="адрес">ссылка</a>
function foo() { ... }
<pre><code>function foo() { ... } </code></pre>
разрешенные теги или посмотреть как будет выглядеть