Красивая AJAX форма для загрузки файлов
В этом уроке мы сделаем небольшую AJAX форму для загрузки файлов, которая позволит посетителям загружать файлы с помощью технологии drag/drop или при помощи обычного выбора файлов.
Мы будем использовать плагины jQuery File Upload и jQuery Knob для отображения прогресса загрузки.
Т.к. форма будет иметь возможность загружать файлы двумя способами, она будет работать даже если drag/drop не поддерживается.
HTML
Как обычно, начнем с HTML5 разметки:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>Mini Ajax File Upload Form</title> <!-- Google web fonts --> <link href="http://fonts.googleapis.com/css?family=PT+Sans+Narrow:400,700" rel='stylesheet' /> <!-- The main CSS file --> <link href="assets/css/style.css" rel="stylesheet" /> </head> <body> <form id="upload" method="post" action="upload.php" enctype="multipart/form-data"> <div id="drop"> Drop Here <a>Browse</a> <input type="file" name="upl" multiple /> </div> <ul> <!-- загрузки будут показаны здесь --> </ul> </form> <!-- JavaScript Includes --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script src="assets/js/jquery.knob.js"></script> <!-- jQuery File Upload Dependencies --> <script src="assets/js/jquery.ui.widget.js"></script> <script src="assets/js/jquery.iframe-transport.js"></script> <script src="assets/js/jquery.fileupload.js"></script> <!-- main JS file --> <script src="assets/js/script.js"></script> </body> </html>
В теге <head> нашего документа, подключаем шрифты Google Webfonts, а перед закрытием тега <body> — JavaScript библиотеки: jQuery, jQuery Knob и jQuery File Upload.
Главный элемент страницы — форма #upload. Внутри нее элемент #drop (принимает файлы с использованием drag&drop) и список, в котором будут отображаться загружаемые файлы. Разметка, которая будет генерироваться для загруженных файлов:
<li class="working"> <input type="text" value="0" data-width="48" data-height="48" data-fgColor="#0788a5" data-readOnly="1" data-bgColor="#3e4043" /> <p>Sunset.jpg <i>145 KB</i></p> <span></span> </li>
Элемент input будет спрятан с помощью CSS. Он нужен для инициализации плагина jQuery Knob, который будет рисовать шкалу процесса загрузки файла. Input имеет атрибуты data-*, которые используются для обновления шкалы. Позже, когда мы будет отслеживать прогресс загрузки, мы будем обновлять эти значения для перерисовки шкалы. span будет содержать зеленую галку или красный крест.
jQuery
У посетителя будет 2 способа загрузки файла:
- Перетащить файл в окно браузера (в IE не работает).
- Нажатием на кнопку browse. Будет имитировано нажатие на спрятанный input и показано системное окно выбора файлов. Обратите внимание, что input имеет параметр multiple параметр, что позволит выбирать много файлов за один раз.
Когда файлы будут выбраны, они помещаются в очередь для последующей автоматической загрузки:
$(function(){ var ul = $('#upload ul'); $('#drop a').click(function(){ // имитация нажатия на поле выбора файла $(this).parent().find('input').click(); }); // инициализация плагина jQuery File Upload $('#upload').fileupload({ // этот элемент будет принимать перетаскиваемые на него файлы dropZone: $('#drop'), // Функция будет вызвана при помещении файла в очередь add: function (e, data) { var tpl = $('<li><input type="text" value="0" data-width="48" data-height="48"'+ ' data-fgColor="#0788a5" data-readOnly="1" data-bgColor="#3e4043" /><p></p><span></span></li>'); // вывод имени и размера файла tpl.find('p').text(data.files[0].name) .append('<i>' + formatFileSize(data.files[0].size) + '</i>'); data.context = tpl.appendTo(ul); // инициализация плагина jQuery Knob tpl.find('input').knob(); // отслеживание нажатия на иконку отмены tpl.find('span').click(function(){ if(tpl.hasClass('working')){ jqXHR.abort(); } tpl.fadeOut(function(){ tpl.remove(); }); }); // Автоматически загружаем файл при добавлении в очередь var jqXHR = data.submit(); }, progress: function(e, data){ // Вычисление процента загрузки var progress = parseInt(data.loaded / data.total * 100, 10); // обновляем шкалу data.context.find('input').val(progress).change(); if(progress == 100){ data.context.removeClass('working'); } }, fail:function(e, data){ // что-то пошло не так data.context.addClass('error'); } }); $(document).on('drop dragover', function (e) { e.preventDefault(); }); // вспомогательная функция, которая форматирует размер файла function formatFileSize(bytes) { if (typeof bytes !== 'number') { return ''; } if (bytes >= 1000000000) { return (bytes / 1000000000).toFixed(2) + ' GB'; } if (bytes >= 1000000) { return (bytes / 1000000).toFixed(2) + ' MB'; } return (bytes / 1000).toFixed(2) + ' KB'; } });
В jQuery File Upload есть собственный интерфейс, но мы используем базовую версию плагина для создания собственного дизайна интерфейса. И чтобы наш интерфейс работал, мы передаем плагину несколько параметров / колбэков:
- dropZone – этот параметр содержит jQuery селектор, который будет принимать перетаскиваемые файлы. Файлы, брошенные на него, будут добавлены в очередь загрузки.
- add – функция вызывается при добавлении файла в очередь загрузки. Она будет генерировать разметку для файлов и вызвать метод
data.submit()
. - progress – Эта функция будет вызываться каждые 100ms (можно изменить). Второй аргумент содержит размер файла и количество загруженных байт. Это позволяет отслеживать прогресс и обновлять шкалу.
- fail – функция вызывается при возникновении ошибки.
PHP
В комплект jQuery File Upload входит также и PHP скрипт для обработки файлов на сервере, но мы напишем свой. Процесс загрузки фалов будет происходить также как и при обычной загрузке, поэтому всю информацию о них мы можем получить из глобального массива $_FILES:
<?php // разрешенные форматы $allowed = array('png', 'jpg', 'gif','zip'); if(isset($_FILES['upl']) && $_FILES['upl']['error'] == 0){ $extension = pathinfo($_FILES['upl']['name'], PATHINFO_EXTENSION); if(!in_array(strtolower($extension), $allowed)){ echo '{"status":"error"}'; exit; } if(move_uploaded_file($_FILES['upl']['tmp_name'], 'uploads/'.$_FILES['upl']['name'])){ echo '{"status":"success"}'; exit; } } echo '{"status":"error"}'; exit;
Как уже говорилось, файлы будут помещаться в очередь и загружаться друг за другом, поэтому обрабатывать на PHP очень легко.
Готово!
Понравилась форма, удобная, работает, хотел прикрутить мульти загрузку видео файлов на ютуб но не получилось. По одному хорошо работает эта форма:
Может попробуете сделать?
Привет, а можешь показать как сделать так, чтобы можно было загружать только один файл?
такой же вопрос, очень нужно
Всё супер! Красиво и т.д., но чёт пытался отправить .ехе файл размером чуть больше 20Мб и он не залился в папку -:( Хотя на странице загрузки был зеленый чекбокс, типа всё нормально прошло. Ограничений по размеру файлов в коде не нашел…
// разрешенные форматы
$allowed = array(‘png’, ‘jpg’, ‘gif’,’zip’);
замени на
$allowed = array(‘png’, ‘jpg’, ‘gif’,’zip’,’exe’);
в js вообще никак не отслеживается «{«status»:»error»}, {«status»:»success»}», как тогда сказачать что файл не соответсвует требованиям?
Здравствуйте.
Как сделать, чтобы после загрузки появлялась ссылка на закаченный файл?
Вам нужно занести данные в БД (mysql), а потом сделать редирект, на тот юрл который человек загрузил, к примеру можно по ID сделать, или NAME FILE.
Спасибо, отличная статья!
Только вот не подскажите как обработать события «{«status»:»error»}, {«status»:»success»}»?
Т.к. внешне все Окей, а по факту о том что файл не прошел условия отбора (формат, размер…) пользователь не знает — всегда зеленая галка выводиться
Подскажите как сделать в сплывающем окне такую форму?
Я сделал добавление, теперь мне нужно сделать редактирование файлов. Как при нажатии кнопки редактировать передать список файлов плагину, чтобы потом можно было удалить случайно загруженные файлы?
Файл больше 50-и мб не загружается на сервер,а скрипт ставит галочку «успешно».Помогите
Извините,а как сделать чтобы файлы с одинаковыми именами сохранялись все по типу как в виндовс image.jpg image(1).jpg.Просто столкнулся при загрузке фото из ios.Спасибо
Спасибо огромное за статью! Конечно, при адаптации к своей задаче тратишь ещё много времени, но ваша статья сделала
70%-ый вклад в моё решение. Удачи Вам в деле несения света в толпу!
Привет. Подскажи пжл а как установить разрешенное общее количество файлов, разрешение на определенный тип файлов и ограничение на общий размер? Можно ли это вообще сделать в плагине или проще сделать отдельный скрипт?
Спасибо, большое. Два дня просидел с официальной документацией, много воды, мало по делу. Именно такие примеры позволяют сделать то что требуется быстро. Очень выручили!
А нужно что либо прописывать что бы заработало сразу с архива? Запускаю с OpenServer.
Согласен, отличная статья!
Только вот не подскажите как обработать события «{«status»:»error»}, {«status»:»success»}»?
Т.к. внешне все Окей, а по факту о том что файл не прошел условия отбора (формат, размер…) пользователь не знает — всегда зеленая галка выводиться
Здравствуйте!
Замените строчку:
На этот код:
А как можно при загрузке изменять имя файла? и например, заносить в базу. То есть, где провести связь между js скриптом и php?
Спасибо за форму загрузки буду юзать на своем проекте
А как получить имя файла в php скрипте. $_FILES[‘upl’][‘name’] вообще не реагирует никак. Ничего не выводит. Ни echo ни var_damp