От автора: в этом учебнике при помощи jQuery, Ajax и Php мы создадим простой загрузчик файлов в стиле Ajax. Тот, который вы легко сможете осуществить на своем сайте, дополненный серверной валидацией и валидацией на стороне клиента.
Вступление
Приложение, которое сделаем, будет употреблять гибкость jQuery для того, чтобы можно было выгружать множественные файлы без обновления страницы или переадресации, с полной серверной и клиентской валидацией для предотвращения выгрузки на ваш сервер нежелательных файлов. Каждая секция будет разделена на описания того, что и зачем она выполняет, чтобы вам было проще все понять.
Шаг 1: разметка HTML
Начните с создания документа html и определения формы, которая будет использоваться для загрузчика файлов. Сохраните его как index.html.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "//www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="//www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Ajax Uploader</title> <link rel="stylesheet" href="style.css" type="text/css" media="screen" title="Main" /> <script type=''text/javascript'' src="path/to/jquery.js"></script> <script type="text/javascript" src="path/to/ajax/ajaxupload.3.5.js"></script> <script type="text/javascript"> $(document).ready(function() { // выполнять, когда готов DOM }); </script> </head> <body> <div id="file_holder"> <form action="upload.php" method="post" enctype="multipart/form-data"> <p><label for="userfile">Choose file(s) to upload:</label> <input id="userfile" class="input" type="file" name="userfile" /></p> <div id="loading"><img src="ajax-loader.gif" alt="Loading"/> Loading, please wait...</div> <div id="errormes"></div> <noscript> <input type="submit" value="submit" class="button2" /> </noscript> </form> </div> </body> </html> |
Начинаем свой документ html с добавления обычных doctype, html, тэгов head и body. В head добавляем заголовок, ссылку на таблицу стилей, ссылку на Google jQuery CDN и свой плагин Ajax. Второй тэг script находится там, куда мы будем помещать весь код после того, как документ будет готов.
Внутри body делаем разметку своей страницы при помощи div‘а #file_holder, который станет нашим упаковщиком, формой и нескриптовой кнопкой submit (отправить), которая поможет сохранить юзабилити (простоту и доступность использования), если у пользователя в браузере не включен javascript, ввод загрузчика файлов и два div’а, которые будут содержать изображение загрузки, а также сообщения об ошибках.
Если у нашего пользователя не активирован javascript, операция form позаботится о передаче файла к upload.php, пользователь будет просто переадресован к ней вместо того, чтобы оставаться на той же странице, и появится сообщение об успешном выполнении или ошибке.
Зависимые файлы
Для изображения загрузки я применил «указатели-стрелки» (arrows) из //www.ajaxload.info/.
Выберите то изображение, которое вам нравится, сохраните его как ajax-loader.gif и выгрузите на свой сервер.
Нам также понадобится плагин Ajax upload. Сохраните его как ajaxupload.js и выгрузите на сервер в папку с названием "ajax".
Шаг 2: стили CSS
Для функциональности этой простой формы требуется всего три строки стилей, скрытие div’а loading на странице загрузки, и расцвечивание текста сообщений об успешном выполнении и ошибке. Конечно, вы можете все улучшить и сделать красивее, чем в моем простом примере загрузчика. Сохраните как style.css.
1 2 3 4 |
/*Документ CSS*/ #loading {display:none;} .error {color:#900000;} .success {color:#009900;} |
Шаг 3: Javascript
Теперь можно приняться за создание функций jQuery, которые заставляют наш загрузчик работать. Нам будет проще разметить, как все работает в целом, разделив секции на действия.
1 2 3 |
var upload = new AjaxUpload('#userfile', { //выгружаем скрипт action: 'upload.php', |
Мы начинаем назначение переменных своего загрузчика Ajax, во-первых, с установки ввода #userfile как переменной загрузки, а затем назначаем действие, с которого начинает действовать ввод, когда выбирается файл.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
onSubmit : function(file, extension){ //показываем анимацию загрузки $("#loading").show(); //проверяем расширение файла if (! (extension && /^(jpg|png|jpeg|gif)$/.test(extension))){ // если расширение не разрешено $("#loading").hide(); $("<span class="error">Ошибка: Невеный формат файла</span>").appendTo("#file_holder #errormes"); // отменяем выгрузку return false; } else { // убираем сообщение об ошибке $('.error').hide(); } //посылаем данные upload.setData({'file': file}); }, |
Вышеприведенный фрагмент говорит загрузчику что делать, как только файл выбран из нашего файлового ввода. Во-первых, показывается анимация загрузки, пока проверяется расширение файла. Если расширение файла не совпадает с предопределенными, выгрузка останавливается и пользователю показывается сообщение об ошибке. Как только пользователь предпринимает новую попытку с правильным расширением файла, сообщение об ошибке убирается, и данные файла предаются в файл upload.php при помощи команды setData.
1 2 3 4 5 6 7 8 9 10 |
onComplete : function(file, response){ //скрываем анимацию загрузки $("#loading").hide(); //добавляем display:block в держатель сообщения о выполнении $(".success").css("display", "block"); //находим div в iFrame и прикрепляем к сообщению об ошибке var oBody = $(".iframe").contents().find("div"); //добавляем iFrame к errormes $(oBody).appendTo("#file_holder #errormes"); } |
Как только наш файл передается в upload.php, до которого мы скоро доберемся, изображение загрузки скрывается и, при помощи захвата статуса из iframe, создаваемого плагином ajaxupload, показывается сообщение об успешном выполнении или ошибке.
Скрипт целиком
Скопируйте и вставьте весь этот код в раздел head своего документа.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
<script type="text/javascript"> $(document).ready(function() { var upload = new AjaxUpload('#userfile', { //выгружаем скрипт //action: 'upload.php', //выгружает отключенное в целях безопасности action: 'upload.htm', onSubmit : function(file, extension){ //показываем анимацию загрузки $("#loading").show(); //проверяем расширение файла if (! (extension && /^(jpg|png|jpeg|gif)$/.test(extension))){ // расширение не разрешено $("#loading").hide(); $("<span class="error">Error: Not a valid file extension</span>").appendTo("#file_holder #errormes"); // отменяем выгрузку return false; } else { // избавляемся от сообщения об ошибке $('.error').hide(); } //высылаем данные upload.setData({'file': file}); }, onComplete : function(file, response){ //скрываем анимацию загрузки $("#loading").hide(); //добавляем display:block в держатель сообщения о выполнении $(".success").css("display", "block"); //находим div в iFrame и прикрепляем к сообщению об ошибке var oBody = $(".iframe").contents().find("div"); //добавляем iFrame к errormes td $(oBody).appendTo("#file_holder #errormes"); } }); }); </script> |
Шаг 4: PHP
Файл php делает действительную выгрузку на наш сервер в то время, как функции, которые мы приведем в исполнение, обеспечивают валидацию, чтобы убедиться, что выгруженный файл остается в пределах установленных нами правил. Объяснить все проще поможет разбиение этого файла на секции.
1 2 3 4 5 6 |
$max_filesize = 2097152; // максимальный размер файла в БАЙТАХ. $allowed_filetypes = array('.jpg','.jpeg','.gif','.png'); // Это будут виды файлов, которые пройдут проверку (валидацию). $filename = $_FILES['userfile']['name']; // получаем название файла (включая его расширение). $ext = substr($filename, strpos($filename,'.'), strlen($filename)-1); // Получаем расширение из названия файла. $file_strip = str_replace(" ","_",$filename); //Замещаем пробелы в названии файла $upload_path = '/path/to/uploads/'; //устанавливаем путь выгрузки |
Хотя многое тут и так понятно, я поясню, что выполняет все вышеприведенное.
Переменная $max_filesize определяет максимальный размер разрешенного для выгрузки файла, в данный момент она установлена на 2mb (так по умолчанию выставляют свои серверы большинство хостинг-провайдеров), определенные в байтах.
Переменная $filename получает из ввода #userfile название файла целиком, включая расширение.
Переменная $ext проверяет правильность расширения на соответствие массиву $allowed_filetypes.
Переменная $allowed_filetypes выстраивает и располагает в определенном порядке виды файлов для ссылки, когда запускается проверка в нижней части кода, до которого мы вскоре доберемся.
$file_strip замещает любые пробелы в названии файла подчеркиваниями, зачем? Если имя файла используется в url, таком как ссылка на изображение и т.д., пробелы часто замещаются на 20% созданием адреса sloppy и его сложно индексировать поисковикам.
Наконец, $upload_path определяет папку, в которую будут перемещаться выгрузки, соответствующую домашней на вашем сервере. Другими словами, большинство серверов конфигурируются файловой структурой вроде этой:/home/yourusername/yoursite.com/path/to/uploads/. Убедитесь, что используете полный путь с начальными и конечными метками "/".
Находим корневой каталог сервера
Чтобы легко найти путь, который нужно здесь ввести, попробуйте выгрузить на сервер нижеприведенный скрипт php, назвать его root.php и получить к нему доступ из своего браузера. Убедитесь, что после того, как нашли корневой каталог своего сервера, вы удалили файл, чтобы не выставлять его напоказ.
1 2 |
<?php $server = $_SERVER['DOCUMENT_ROOT']; ?> <?php echo $server; ?> |
Остальная часть скрипта просто обрабатывает функции, основанные на установленных нами в вышеприведенном коде параметрах.
1 2 3 4 |
// Проверяем, разрешен ли тип файла, если не DIE, и информируем пользователя. if(!in_array($ext,$allowed_filetypes)) { die('<div class="error">Загружаемый тип файла недостим.</div>'); } |
Вначале проверяется массив видов файлов, и если данного расширения в нем нет, скрипт останавливает выполнение (die) и выводит сообщение об ошибке.
1 2 3 4 |
// Теперь проверяем размер файла, если он слишком большой, то DIE и информируем пользователя. if(filesize($_FILES['userfile']['tmp_name']) > $max_filesize) { die('<div class="error">Загружаемы файл слишком большой.</div>'); } |
Проверьте размер файла на соответствие установленной переменной, если он больше, скрипт останавливает выполнение (die) и выводит сообщение об ошибке.
1 2 3 |
// Проверяем, можно ли выгрузить в определенный путь, если нет, то DIE и информируем пользователя. if(!is_writable($upload_path)) { die('<div class="error">Вы не можете загружать в папку /uploads/. Измените права на папку.</div>'); |
Эта часть кода проверяет папку на сервере, чтобы убедиться, что она перезаписываемая, или пригодна для размещения в ней файла нашим скриптом. Если нет, снова применяем (die) и выводим сообщение пользователю.
1 2 3 4 5 6 |
// Перемещаем файл, если все прошло проверку. if(move_uploaded_file($_FILES['userfile']['tmp_name'],$upload_path . $file_strip)) { echo '<div class="success">'. $file_strip .' Файл успешно загружен.</div>'; // Получилось. } else { echo '<div class="error">'. $file_strip .' Файл не загружен. Попробуйте позже.</div>>'; // Не получилось :(. } |
Если файл прошел все проверки на стороне сервера, то он перемещается в папку загрузок. Если что-то еще пошло не так, наш пользователь извещается о том, что следует предпринять новую попытку.
upload.php
Скопируйте и вставьте весь этот код в новый файл и сохраните его как upload.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<?php $max_filesize = 2097152; // Максимальный размер файла в БАЙТАХ. $allowed_filetypes = array('.jpg','.jpeg','.gif','.png'); // Это будут виды файлов, которые пройдут валидацию. $filename = $_FILES['userfile']['name']; // Получаем название файла (включая его расширение). $ext = substr($filename, strpos($filename,'.'), strlen($filename)-1); // Получаем расширение имени файла. $file_strip = str_replace(" ","_",$filename); //Замещаем пробелы в названии файла $upload_path = '/path/to/uploads/'; //Устанавливаем путь выгрузки // Проверяем, разрешен ли вид файла, если нет - DIE и информируем пользователя. if(!in_array($ext,$allowed_filetypes)) { die('<div class="error"> Загружаемый тип файла недостим.</div>'); } // Теперь проверяем размер файла, если он слишком большой, то DIE и информируем пользователя. if(filesize($_FILES['userfile']['tmp_name']) > $max_filesize) { die('<div class="error"> Загружаемы файл слишком большой.</div>'); } // Проверяем, можно ли выгрузить в определенный путь, если нет, то DIE и информируем пользователя. if(!is_writable($upload_path)) { die('<div class="error"> Вы не можете загружать в папку /uploads/. Измените права на папку.</div>'); } // Перемещаем файл, если он прошел все проверки. if(move_uploaded_file($_FILES['userfile']['tmp_name'],$upload_path . $file_strip)) { echo '<div class="success">'. $file_strip .' Файл успешно загружен. </div>>'; // Получилось. } else { echo '<div class="error">'. $file_strip . Файл не загружен. Попробуйте позже.</div>'; // Не получилось :(. } ?> |
Устанавливаем права доступа к файлам
Перед тем, как протестировать свой загрузчик, нужно убедиться, что папка, куда пойдут наши выгрузки, перезаписываемая. Я обойдусь без обычных вещей типа CHMOD на 777 и пойду дальше. Если вы знакомы с использованием клиента Telnet, эта часть – не для вас, она для тех, кто был совсем как я, когда начинал, жаждущим прочесть и выучить CHMOD и тут же подумавшим «Что за фигня?»
В сущности, откройте свой ftp-клиент и пройдите в папку, куда перемещаются загрузки из этого загрузчика. Щелкните правой кнопкой мыши по папке и выберите свойства (properties), убедитесь, что все окна установлены на read, write и execute, (777) нажмите OK и закройте окно.
Пройдите в Dreamweaver к папке с выгрузками во время дистанционного управления и щелкните правой кнопкой мыши по файлу, выберите «Установить права доступа» (Set permissions) и далее следуйте вышеприведенным инструкциям.
Шаг 5: попробуйте
Последний шаг – попробовать и посмотреть, работает он или нет. Если ничего не происходит или что-то ломается, вернитесь обратно, пройдите по тщательно расписанным мною шагам и определите, что не так. Не бойтесь скачать исходные файлы и проверить демо-версию, чтобы лучше понять, как работает загрузчик.
Спасибо за прочтение!
Автор: VagrantRadio
Источник: www.vagrantradio.com
Редакция: Рог Виктор и Андрей Бернацкий. Команда webformyself.
Комментарии (12)