Содержание

SWFUpload. AJAX загрузка файлов на сервер

Введение

Асинхронные запросы в web-разработке не редкость. Принцип очень прост:

  1. Формируем в JavaScript необходимые данные.
  2. Оправляем на сервер.
  3. Получаем ответ и перестраиваем страницу опять же с помощью JavaScript.

Но все меняется когда мы начинаем говорить о AJAX передаче данных.

Чтобы понять суть проблемы достаточно взглянуть на обычную передачу файла на сервер - в POST параметрах передается тело файла. А как известно JavaScript не может получить доступ к файлам, соответственно передать тело файла в AJAX запрос мы не можем.

Одним из вариантов решения данной проблемы является использование flesh-загрузчиков, которых сегодня огромное множество.

Однако у многих есть два существенных ограничения (сугубо по моему личному мнению):

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

И еще одна маленький бонус - можно настроить фильтрацию файлов по типам и размеру еще до отправки файлов на сервер.


О SWFUpload

Сайт разработчиков: swfupload.org
Полная документация: swfupload documentation

Для работы с загрузчиком необходимо по крайней мере следующие файлы:


Инициализация

Для инициализации загрузчика необходимо подключить библиотеку 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. По большому счету для большинства приложений достаточно использовать всего лишь два метода (оба метода приведены в примерах обработчиков событий).

startUpload(file_id)

Запускает загрузку файла.

Входные параметры:

Выходные параметры:

Не возвращает данных.

cancelUpload(file_id, trigger_error_event)

Отменяет загрузку файла и убирает его из очереди.

Входные параметры:

Выходные параметры:

Не возвращает данных.

stopUpload()

Останавливает текущую загрузку файла и заново помещает его в очередь.

Входные параметры:

Нет входных параметров.

Выходные параметры:

Не возвращает данных.

getStats()

Возвращает статистические данные.

Входные параметры:

Нет входных параметров.

Выходные параметры:

getFile(file_id|index)

Возвращает данные о файле.

Входные параметры:

Выходные параметры:


События

При каждом изменении состояния flesh генерирует соответствующее событие. Именно создание своих обработчиков этих событий и делает SWFUpload невероятно гибким инструментом.

И так чтобы показать все картину целиком я покажу в каком порядке появляются события.

Давайте рассмотрим обработчики основных событий.

fileQueued

Событие 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

Событие 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

Событие fileDialogComplete возникает после закрытия и постановки файлов в очередь.

Событие передает обработчику следующую информацию:

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

Пример:

JavaScript:
 
function myFileDialogCompleteFunction(selected, queued, queued_total) {
  try {
    //к примеру, запускаем загрузку файлов
    this.startUpload();
  } catch (ex) {
    //обрабатываем ошибку
    //к примеру, выводим в debug
    this.debug(ex);
  }
};

uploadStart

Событие возникает непосредственно перед загрузкой файла.

Событие передает обработчику следующую информацию:

Пример:

JavaScript:
 
function myUploadStartFunction(file) {
  try {
    //вывод данных о файле на страницу
    //к примеру, выводим размер файла и статус "Загружается" в <div id="filestatus">
    var status = document.getElementById('filestatus');
    status.innerHTML = "Размер файла: " + file.size + " байт. Загружается...";
 
  } catch (ex) {
    //обрабатываем ошибку
    //к примеру, выводим в debug
    this.debug(ex);
  }
};

uploadProgress

Событие периодически возникает в процессе загрузки файла.

Событие передает обработчику следующую информацию:

Пример:

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

Событие 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 возникает при удачной загрузке файла

Событие передает обработчику следующую информацию:

Если по каким-либо причинам после удачной загрузки файла не вызвано событие 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);
  }
};

uploadComplete

Событие всегда возникает в конце цикла загрузки файла, сразу после uploadSuccess или uploadError.

Событие передает обработчику следующую информацию:

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

Пример:

JavaScript:
 
function myUploadCompleteFunction(file) {
  try {
    //вывод сообщения о загрузке файла
    //к примеру, проверяем есть ли еще файлы в очереди и запускаем их загрузку
    if (this.getStats().files_queued != 0) {
      this.startUpload();
    }
  } catch (ex) {
    //обрабатываем ошибку
    //к примеру, выводим в debug
    this.debug(ex);
  }
};

Резюме

SWFUplaod очень гибкий инструмент для AJAX-загрузки файлов, но при этом требует более глубоких знаний в области программирования.

Я рассказал лишь о части методов и привел простенькие примеры обработчиков событий, но надеюсь что этот материал поможет вам сэкономить время на начальном этапе изучения SWFUpload.

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