Тема загрузки файлов без перезагрузки страницы поднималась уже неоднократно. Даже я как-то давно
писал про это. В основном рассматривались решения без флэша, но сегодня я хотел бы поговорить про плагин для jquery с использованием флэша, а именно о
JQuery Uploadify.
Конечно, можно использовать и другой флэшевский загрузчик
SWFUpload, но Uploadify, по моему мнению, на порядок легче и проще, вполне подходит для большинства целей, ну и конечно не забываем, что это плагин для нашего любимого jquery, что избавляет нас от подключения еще каких-либо библиотек ;)
Теперь рассмотрим всё на примере.
Использовать плагин очень просто, как и большинство других jquery плагинов ;)
Естественно, сперва подключаем js файлы:
<script type="text/javascript" src="jquery.uploadify.v2.1.0.min.js"></script>
<script type="text/javascript" src="swfobject.js"></script>
* This source code was highlighted with Source Code Highlighter.
Все успели заметить
swfobject.js? Отклоняться от темы не буду, почитать про SWFObject и всего его плюсы можно
в этом посте на Хабре.
Далее идёт следующий код:
$(document).ready(function() {
$("#uploadify").uploadify({
'uploader' : 'uploadify.swf',
'script' : 'functions.php',
'checkscript' : 'check.php',
'cancelImg' : 'cancel.png',
'queueID' : 'fileQueue',
'auto' : true,
'multi' : true,
'fileDesc' : 'jpg',
'fileExt' : '*.jpg',
'onComplete' : function(event,queueID,fileObj,response,data) {$('#response').append(response);}
});
});
* This source code was highlighted with Source Code Highlighter.
Теперь немного подробнее.
uploader — путь до самого флэш загрузчика uploadify.swf
script — это путь до нашего файла обработчика, у меня это файл functions.php, но в архиве с библотекой он именуется как uploadify.php.
checkscript — путь до скрипта, который будет проверять наш файл до загрузки его на сервер. В файле, идущем в архиве с плагином, проверяют существования файла с таким же именем на сервере.
cancelImg — путь до картинки, которая будет символизировать удаления файла.
queueID — id элемента, в котором будет содержаться список выбранных нами файлов. По умолчанию он создаётся ниже браузерной кнопки выбора файла.
auto — параметр, отвечающий, будут ли файлы загружаться автоматически сразу после их выбора, или нет. Если стоит значение
false, то для начала загрузки можно использовать этот код:
<a href="javascript:$('#uploadify').uploadifyUpload();">Загрузить файлы.</a>
* This source code was highlighted with Source Code Highlighter.
Естественно, можно повесить вместо ссылки картинку или кнопку, тут уже на Ваш выбор.
multi — будет ли наш плагин служить для загрузки нескольких файлов, иль не будет :) Для загрузки одного файла можно обойтись и без флэша, так что смело оставляем тут
true.
fileDesc — типы файлов в диалоге выбора. У меня тут стоят только jpg файлы.
fileExt — расширения файлов, разрешенных для загрузки. Смело можно добавить к моим jpg и другие,
например: *.jpg;*.bmp;*.png.
Незабываем добавить эти типы файлов и в fileDesc, иначе не сможете выбрать эти файлы в диалоговом окне ;)
Также советую всё-таки проверять типы файлов на стороне сервера, ибо такую проверку на стороне клиента легко обойти ;)
onComplete — функция, которая будет вызвана сразу после загрузки файла. Замечу, не после загрузки всех файлов, для этого есть
onAllComplete, а именно одного файла из очереди.
Данная функция будет вызываться каждый раз, как будет загружен очередной файл. У меня вызывается функция, которая получается ответ от моего обработчика
functions.php и вставляет его в
div с id
response:
function(event,queueID,fileObj,response,data) {$('#response').append(response);}
* This source code was highlighted with Source Code Highlighter.
Страница самого плагина:
http://www.uploadify.com/
Страница с расширенной документацией по всем параметрам и функциям:
http://www.uploadify.com/documentation/
Вот собственно и всё. Будут вопросы — с радостью попытаюсь на них ответить и всячески помочь ;)
_________
Текст подготовлен в
ХабраРедакторе
комментарии (91)
Так что годиться только только для фоток (и то не очень больших), а прочих мелких файликов =(
Там в дефолтовой поставке идет скрипт на проверку размера и формата совместимости — уверен проблема была в нем (у себя переделал его сразу)
Подвисаний нет.
Но, сталкивался с конфликтом с антивирусом касперского. Вопрос решился обновлением антивируса до 10 версии и настройкой в нем сайта, на которорый осуществляется аплоад, как доверенного.
А так, скрипт весьма неплохой.
swfupload.googlecode.com
у меня репартеры на autopeople.ru загружают им видео ролики больших размеров (200 мб)
Пока документация не готова, но мне нравится, что получается. Пока в качестве preview кину сюда ссылку на него, вдруг кому пригодится. Лицензия MIT, так что если кому интересно — используйте, подключайтесь к разработке. Пиар проведу, так сказать, предварительный.
bitbucket.org/kmike/gearsuploader/wiki/ru
В самом Uploadify было несколько неприятных глюков, но после последнего апдейта (был в конце лета) почти все хорошо за исключением:
1. Иногда улетает окно выбора файлов если долго искать что выбрать(ФФ+Open Suse 11.1) — возможно проблемы с самим ГТК.
2. Окно выбора файлов не запоминает последнюю директорию, иногда просто не удобно рыскать по попкам (опять же не тестил в вин, в лине возможно проблемы с ГТК).
Одно что не совсем хорошо — в флешке некорректно отображается русский (думаю можно подпилить напильником в флеше)
2) опять же, у меня всё запомнило :) вин. ff 3.5.3
пысы: про попки особенно понравилось ;)))
На данный момент у нас решено только принудильной подачей своей id сессии как дублирующей :(
У меня получилось загрузить только .jpg, и то, имя оказалось пустым.
$valid_chars_regex = 'А-Я.A-Z0-9_ !@#$%^&()+={}\[\]\',~`-';Получилось хотя бы избегать пустоты, вместо имени файла.
почитайте на сайте про onAllComplete .
Если не разберетесь — сделаем примерчик :)
Вы, судя по всему, меня немного не правильно поняли — о количестве переданной информации во время передачи, т.е. чтобы был прогресс загрузки. Сейчас у меня получается видеть только финиш загрузки, без каких-либо промежуточных данных.
Как понимаю, помимо прогресс бара вы хотите добавить отображения количества загруженных байт?
Думаю это то, что вам нужно :)
А сам прогресс загрузки реализовал без использования этого модуля — понял силу jQuery.
Пробовал другие плагины — ситуация аналогичная.
Поэтому, необходимо оставлять возможность стандартного аплоада через html.
По плагину: недавно внедрил на свой сайт — интерфейс красивый, но есть глючки в старых версиях плагина. Причем примеры идут со старыми, нерабочими версиями, что вносит путаницу, и нет дебагера, позволяющего понять что происходит. В итоге отлаживал скрипты в swfupload (там есть дебагер), а потом подменил его на uploadify. Так же есть нюанс — скрипт аплоада должен быть в отдельной библиотеке или в отдельном блоке script (об этом написано на форуме плагина, пока нашел в чём дело — голову сломал). Вобщем внедрить сложно, но заставить работать — можно.
Посмотреть плагин в действии можно тут:
mp3tter.com
Проверь эти настройки в php.ini:
; Maximum size of POST data that PHP will accept.
post_max_size = 20M
; Whether to allow HTTP file uploads.
file_uploads = On
; Maximum allowed size for uploaded files.
upload_max_filesize = 20M
Для сервера nginx — в секции http также необходимо указать:
keepalive_timeout 0;//!!!
client_max_body_size 20m;//
И разрешить обработку флеша, у меня в конфиге это реализовано так:
if (-f $request_filename) {
expires max;
break;
}
if ($request_filename !~ (js|css|ico|gif|jpg|m3u|swf|zip|png|images|robots\.txt|my_index_file\.php*) ) {
rewrite ^/(.*)$ /mp3tter.php/$1 last;
}
1. файл загружается во флешку
2. файл сохраняется из флеш в темповую директорию сервера
3. скрипту передается массив $_FILES содержащий имена загруженных файлов
как то так.
Я думаю я относился бы к вашему любимому jquery если бы не было так много людей что без него ничего не могут сделать на жаваскрипте.
Я ЛЮБЛЮ JQUERY больше чем PROTOTYPE :)
А если писать что-то серьёзное без фреймворка — это уже велосипед (:
Даже скрипт с примером этого не делает у меня.
А оттуда php-командой move_uploaded_file можно его переместить куда требуется.
1. Если на клиентской стороне работает Касперский, то загрузка каждого файла (прогрессбар) сразу показывает 100%. При отключеном касперском — нормально.
2. (хотя тут возможно виноват сервер) Загрузка больших файлов (около 500Мб) доходит до 100% и все, никаких действий от скрипта вы не дождетесь, возникает ощущение, что скрипт ждет json, но не получает и ожидание это может продолжаться вечно!
IO Error — бывает, но не часто…
(Настройка/Защита/Вэб антивирус/Настройка/Оптимизация проверки/кнопка Выбрать/ добавьте сюда записть типа *yoursite.com*), и все будет работать.
Так получается, что скрипт просто отсылает данные на сервер независимо от браузера.
function startUpload()
{
var twitt = 'false';
if (document.getElementById('twitt_it').checked == true) twitt = 'true';
$('#uploadify').uploadifySettings('scriptData',{'tag':$('#tag').val(),'msg':$('#msg').val(),'twitt_it':twitt,'author':'recoilme'});
$('#uploadify').uploadifyUpload();
}
Т.е. оно, конечно, не сильно смертельно, если речь идёт об админке — куда доступ одного человека разрешён, другое дело когда это сервис, где толпа народу, имеющая право что-то загружать. Вот тогда уже не так всё кучеряво хотя терпимо.
Кстати, если стоит суровый скрипт (у меня в CakePHP всё сурьёзно) — следует ещё и проверку UserAgent отключать — ибо сессия сессией, а агент-то меняется :)
Спасибо за плагин
Настройка плагина (думаю спокойно можно вынести в отдельный js, но не пробывал)
$(document).ready(function() {
$('#fileUpload').fileUpload({
'uploader': '/system/application/modules/upload/uploader.swf',
'script': '/system/application/modules/upload/upload.php',
'folder': '/assets/images/tmp',
'cancelImg': '/system/application/modules/upload/cancel.png',
'multi': true,
'buttonText': 'select files',
'displayData': 'percentage',
'simUploadLimit': 1,
'fileExt': '*.jpg;*.jpeg;*.gif;*.png',
onAllComplete: function(event, data){
$("#loadTips").append(«Файлов загружено: „+data.filesUploaded+“
»);
$("#loadTips").append(«Ошибок: „+data.errors+“
»);
$("#loadTips").append(«Загружено: „+data.allBytesLoaded+“ байт
»);
},
onComplete: function(event, queueID, fileObj, response, data){
idResp=''; // нужно для моего обработчика резалта онАджаксКомплит
$.post('http://<?=$_SERVER['SERVER_NAME']?>/admin/upload/doupload/', 'name='+fileObj.name+'&path='+fileObj.filePath+'&module=<?=$module;?>&id_pos=<?=$id_pos;?>&conf_name=<?=$conf_name?>', // после загрузки делаем запрос на обработчик (ниже будет пример)
function(data){
idResp = ''; // нужно для моего обработчика резалта онАджаксКомплит
$.get('http://<?=$_SERVER['SERVER_NAME']?>/admin/upload/index/'+data+'/', '',
function(data){
$("#gallery_box").fadeIn(250, function() { $("#gallery_box").append(data)}); /* сюда попадают сразу загруженные изображения */
}
);
});
},
onError: function(event, queueID, fileD, errorObj){
$("#loadTips").append(«event: „+event+“
»);
$("#loadTips").append(«queueID: „+queueID+“
»);
$("#loadTips").append(«fileD: „+fileD+“
»);
$("#loadTips").append(«errorObj.status: „+errorObj.status+“
»);
$("#loadTips").append(«errorObj.text: „+errorObj.text+“
»);
}
});
метод что используется после загрузки /admin/upload/doupload/
function doupload(){
$data['name'] = $this->input->post('name');
$data['path'] = $this->input->post('path');
/* тут любая обработка уже загруженных изображений в folder: /assets/images/tmp у меня — зум, первоначальная обработка, запись в БД… */
}
Думаю этого достаточно. Сам плагин подключается в контроллеры через плагин галереи (сделан по аналогии как делать плагин подключения FCK едитора)
Я долго думал, почему же оно у меня не работает :)
А «folder» как-то не понятно рабоает, все равно добавляет путь к скрипту, хотя в доке и написано: For absolute paths prefix the path with either '/' or 'http'.
а в описании тоже не даёт?
Или скажем поменять внешний динамически создаваемых вид элементов аплоадера (тот-же програесс бар, когда одинм css не обойтись)?
www.uploadify.com/forum/viewtopic.php?f=3&t=263&p=1099&hilit=localization
jQuery(document).ready(function() {
jQuery("#uploadify").uploadify({
'uploader': '/flash/uploadify.swf',
'script': '/test.php',
'cancelImg': '/img/admin/cancel.png',
'queueID': 'fileQueue',
'auto': true,
'multi': false,
'method': 'GET',
'scriptAccess': 'always',
'fileDesc': 'Audio (*.mp3)',
'fileExt': '*.mp3',
'onError': function(event,queueID,fileObj,errorObj) { },
'onComplete': function(event,queueID,fileObj,response,data) { }
});
});
</script>
лог апача пишет следующее:
«POST /test.php?folder=%2Fmusic%2F&fileext=%2A%2Emp3 HTTP/1.1» 302 207 "-" «Shockwave Flash» 24188 4
и ещё странная штука. флешка 2 раза вызывает test.php в начале загрузки и в конце.
Тоесть, если у меня произошла ошибка на стадии, например, копирования файла из временной директории в директорию назначения — как сообщить об этом в скрипт, отправивший файл?
Там в примере uploadify.php в конце есть строкаи
echo '1';
и
echo 'Invalid file type.';
Но как их ловить — непонятно, onError не вызывается, в onAllComplete тоже errors: 0… куда рыть?