Асинхронные запросы в web-разработке не редкость. Принцип очень прост:
Но все меняется когда мы начинаем говорить о AJAX передаче данных.
Чтобы понять суть проблемы достаточно взглянуть на обычную передачу файла на сервер - в POST параметрах передается тело файла. А как известно JavaScript не может получить доступ к файлам, соответственно передать тело файла в AJAX запрос мы не можем.
Одним из вариантов решения данной проблемы является использование flesh-загрузчиков, которых сегодня огромное множество.
Однако у многих есть два существенных ограничения (сугубо по моему личному мнению):
Вся прелесть SWFUpload заключается в том, что он позволяет выбирать и загружать сразу несколько файлов, а внешним видом flash является только одна картинка кнопки загрузки. При этом flash передает всю информацию о загружаемых файлах в JavaScript, на основании, которой можно построить абсолютно любое отображение процесса загрузки файлов.
И еще одна маленький бонус - можно настроить фильтрацию файлов по типам и размеру еще до отправки файлов на сервер.
Сайт разработчиков: swfupload.org
Полная документация: swfupload documentation
Для работы с загрузчиком необходимо по крайней мере следующие файлы:
swfupload.js
- собственно сама библиотека.swfupload.swf
- flash-загрузчик.swfupload_handlers.js
- скрипты обработчиков событий (этот файл мы создадим сами).ajax.php
- обработчик файлов на стороне сервера (его мы тоже напишем сами).button_sprite.png
- картинка кнопки (четыре кадра).
Для инициализации загрузчика необходимо подключить библиотеку swfupload.js
и разместить следующий код:
JavaScript: var loader = new SWFUpload({ button_placeholder_id: "loader" });
HTML:
<div id="loader"></div>
Настройка загрузчика происходит путем передачи объекта с параметрами при инициализации (комплексная настройка) или путем задания отдельных параметров, используя методы самого SWFUpload (эти методы здесь рассмотрены не будут, поэтому при необходимости, обратитесь к документации).
Рассмотрим наиболее часто-используемые параметры, разбив их по смысловым группам.
Пример:
JavaScript: var loader = new SWFUpload({ debug: true, upload_url: "/ajax.php", flash_url: "/swfupload.swf" });
Как я уже отмечал, внешний вид flesh загрузчика представляет собой картинку. Единственная особенность этой картинки в том, что она состоит из четырех кадров, отображающих различные состояния кнопки (обычное, наведение курсора, нажатие мыши и еще какое-то ).
Пример:
JavaScript: var loader = new SWFUpload({ button_placeholder_id: "loader", button_image_url: "/button_sprite.png", button_width: 60, button_height: 23, button_text: "<b>Click</b> <span class='redText'>here</span>" });
Пример:
JavaScript: var loader = new SWFUpload({ file_post_name: "filedata", file_types: "*.jpg;*.gif;*.png", file_types_description: "Фотографии", file_size_limit: "2 MB" });
Параметры обработчиков по своей сути являются именами функций, которые должны будут обрабатывать эти события.
Пример:
JavaScript: var loader = new SWFUpload({ file_queued_handler: myFileQueuedFunction, file_queue_error_handler: myFileQueueErrorFunction, file_dialog_complete_handler: myFileDialogCompleteFunction, upload_start_handler: myUploadStartFunction, upload_progress_handler: myUploadProgressFunction, upload_error_handler: myUploadErrorFunction, upload_success_handler: myUploadSuccessFunction, upload_complete_handler: myUploadCompleteFunction });
Здесь я привожу только параметры обработчиков, которые я наиболее часто использую, все они связаны с процессом загрузки файла. Полный список обработчиков ищите в документации.
Подробное описание представленных обработчиков находится в разделе События.
Хотя это и не обязательно, но практика показала, что лучше определять все обработчики событий связанных с загрузкой.
При желании, можно задать какие-либо свои параметры. Параметры передаются обычным объектом, содержащим наборы ключ:значение.
Пример:
JavaScript: var loader = new SWFUpload({ custom_settings: { my_setting_1: "my_value_1", my_setting_2: "my_value_2", my_setting_3: "my_value_3" } });
Здесь приведен частичный список параметров, за полным перечнем параметров обратитесь к официальной документации.
Здесь мы рассмотрим лишь малую часть методов SWFUpload. По большому счету для большинства приложений достаточно использовать всего лишь два метода (оба метода приведены в примерах обработчиков событий).
Запускает загрузку файла.
Входные параметры:
Выходные параметры:
Не возвращает данных.
Отменяет загрузку файла и убирает его из очереди.
Входные параметры:
Выходные параметры:
Не возвращает данных.
Останавливает текущую загрузку файла и заново помещает его в очередь.
Входные параметры:
Нет входных параметров.
Выходные параметры:
Не возвращает данных.
Возвращает статистические данные.
Входные параметры:
Нет входных параметров.
Выходные параметры:
Возвращает данные о файле.
Входные параметры:
Выходные параметры:
При каждом изменении состояния flesh генерирует соответствующее событие. Именно создание своих обработчиков этих событий и делает SWFUpload невероятно гибким инструментом.
И так чтобы показать все картину целиком я покажу в каком порядке появляются события.
Давайте рассмотрим обработчики основных событий.
Событие fileQueued возникает при удачной постановке файла в очередь загрузки.
Событие передает обработчику следующую информацию:
Пример:
JavaScript: function myFileQueuedFunction(file) { try { //вывод данных о файле на страницу //к примеру, создаем элемент <p> содержащий имя файла и добавляем его в <div id="filelist"> var filelist = document.getElementById('filelist'); var p = document.createElement('P'); p.innerHTML = file.name; filelist .appendChild(p); } catch (ex) { //обрабатываем ошибку //к примеру, выводим в debug this.debug(ex); } };
Событие fileQueueError возникает при появлении ошибки в процессе постановки файла в очередь загрузки.
Событие передает обработчику следующую информацию:
Советую ориентироваться на код ошибки, а не на текст. Коды ошибок находятся в константах SWFUpload.QUEUE_ERROR.
Пример:
JavaScript: function myFileQueueErrorFunction(file, code, message) { try { //вывод ошибки на страницу //к примеру, создаем элемент <p> содержащий имя файла и текст ошибки и добавляем его в <div id="filelist"> var filelist = document.getElementById('filelist'); var p = document.createElement('P'); var error; switch(code) { case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT: error = 'Превышен допустимый размер файла'; break; case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE: error = 'Пустой файл'; break; case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE: error = 'Недопустимое расширение файла'; break; case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED: error = 'Превышен установленный предел количества загрузок'; break; default: error = 'Неизвестная ошибка'; break; } p.innerHTML = file.name + ' - ' + error; filelist .appendChild(p); } catch (ex) { //обрабатываем ошибку //к примеру, выводим в debug this.debug(ex); } };
Событие fileDialogComplete возникает после закрытия и постановки файлов в очередь.
Событие передает обработчику следующую информацию:
Если вы хотите, чтобы загрузка файлов началась автоматически после закрытия диалогового окна, то это событие подходит идеально.
Пример:
JavaScript: function myFileDialogCompleteFunction(selected, queued, queued_total) { try { //к примеру, запускаем загрузку файлов this.startUpload(); } catch (ex) { //обрабатываем ошибку //к примеру, выводим в debug this.debug(ex); } };
Событие возникает непосредственно перед загрузкой файла.
Событие передает обработчику следующую информацию:
Пример:
JavaScript: function myUploadStartFunction(file) { try { //вывод данных о файле на страницу //к примеру, выводим размер файла и статус "Загружается" в <div id="filestatus"> var status = document.getElementById('filestatus'); status.innerHTML = "Размер файла: " + file.size + " байт. Загружается..."; } catch (ex) { //обрабатываем ошибку //к примеру, выводим в debug this.debug(ex); } };
Событие периодически возникает в процессе загрузки файла.
Событие передает обработчику следующую информацию:
Пример:
JavaScript: function myUploadProgressFunction(file, loaded, total) { try { //вывод данных о прогрессе загрузке файла //к примеру, выводим процент загрузки в <div id="fileprogress"> var progress = document.getElementById('fileprogress'); var percent = Math.round(100 * loaded / total); progress.innerHTML = "Загружено: " + percent + "%"; } catch (ex) { //обрабатываем ошибку //к примеру, выводим в debug this.debug(ex); } };
Событие uploadError возникает при появлении ошибки в процессе загрузки файлов.
Событие передает обработчику следующую информацию:
Советую ориентироваться на код ошибки, а не на текст. Коды ошибок находятся в константах SWFUpload.UPLOAD_ERROR.
Пример:
JavaScript: function myUploadErrorFunction(file, code, message) { try { //вывод ошибки на страницу //к примеру, выводим текст ошибки в <div id="filestatus"> var status = document.getElementById('filestatus'); status.innerHTML = "Ошибка: " + message; } catch (ex) { //обрабатываем ошибку //к примеру, выводим в debug this.debug(ex); } };
Событие uploadSuccess возникает при удачной загрузке файла
Событие передает обработчику следующую информацию:
Если по каким-либо причинам после удачной загрузки файла не вызвано событие uploadSuccess, то через определенное время (assume_success_timeout) событие все равно будет вызвано, при этом received_response будет содержать false.
Пример:
JavaScript: function myUploadSuccessFunction(file, serverData, rr) { try { //вывод сообщения о загрузке файла //к примеру, выводим сообщения в <div id="filestatus"> var status = document.getElementById('filestatus'); status.innerHTML = "Файл " + file.name + " загружен."; } catch (ex) { //обрабатываем ошибку //к примеру, выводим в debug this.debug(ex); } };
Событие всегда возникает в конце цикла загрузки файла, сразу после uploadSuccess или uploadError.
Событие передает обработчику следующую информацию:
Вызов события показывает, что цикл загрузки файла завершен. Это отличное место для автоматического запуска загрузки следующего файла.
Пример:
JavaScript: function myUploadCompleteFunction(file) { try { //вывод сообщения о загрузке файла //к примеру, проверяем есть ли еще файлы в очереди и запускаем их загрузку if (this.getStats().files_queued != 0) { this.startUpload(); } } catch (ex) { //обрабатываем ошибку //к примеру, выводим в debug this.debug(ex); } };
SWFUplaod очень гибкий инструмент для AJAX-загрузки файлов, но при этом требует более глубоких знаний в области программирования.
Я рассказал лишь о части методов и привел простенькие примеры обработчиков событий, но надеюсь что этот материал поможет вам сэкономить время на начальном этапе изучения SWFUpload.
Полное описание всех настроек, методов и событий представлено в официальной документации на сайте разработчика.