jQuery AJAX загрузка файлов на сервер
Как загружать любые файлы, например, картинки на сервер с помощью AJAX и jQuery? Делается это довольно просто! И ниже мы все обстоятельно разберем.
В те «древние» времена, когда еще не было jQuery, а может он был, но браузеры были не так наворочены, загрузка файла на сайт с помощью AJAX была делом муторным: через всякие костыли вроде iframe. Я то время не застал, да и кому это теперь интересно. А интересно теперь другое - что сохранение файлов на сайт делается очень просто. Даже не обладающий опытом и пониманием, того как работает AJAX, вебмастер, сможет быстро разобраться что-куда. А эта статья ему в помощь. Если подкрепить эти возможности функциями WordPress, то безопасная обработка и загрузка файлов на сервер становится совсем плёвым и даже интересным делом (пример с WordPress смотрите в конце статьи).
Однако, как бы все просто не было, нужно заметить, что минимальный опыт работы с файлами и базовые знания в Javascript, jQuery и PHP все же необходимы! Минимум, нужно представлять как загружаются файлы на сервер, как в общих чертах работает AJAX и хоть немного надо уметь читать и понимать код.
Описанный ниже метод довольно стабилен, и по сути опирается на Javascript объект new FormData(), базовая поддержка которого есть во всех браузерах.
Для более понятного восприятия материала, он разделен на шаги. На этом все, полетели...
Смотрите также: плагин для упрощения работы с AJAX в WordPress.
AJAX Загрузка файлов: общий пример
Начинается все с наличия на сайте input поля типа file. Нет необходимости, чтобы это поле было частью формы (тега <form>).
Таким образом, у нас есть HTML код с file полем и кнопкой «Загрузить файлы».
<input type="file" multiple="multiple" accept=".txt,image/*"> <a href="#" class="upload_files button">Загрузить файлы</a> <div class="ajax-reply"></div>
Шаг 1. Данные из поля file
Первым шагом, нужно получить данные загружаемых файлов.
При клике на file-поле, появляется окно выбора файлов, после выбора, данные о них сохраняются в input поле, а нам нужно их от туда «забрать». Для этого повесим на событие change JS функцию, которая будет сохранять имеющиеся данные file-поля в JS переменную files:
var files; // переменная. будет содержать данные файлов
// заполняем переменную данными, при изменении значения поля file
jQuery('input[type=file]').on('change', function(){
files = this.files;
});
Шаг 2. Создаем AJAX запрос (по клику)
Данные файлов у нас есть, теперь их нужно отправить через AJAX. Вешаем это событие на клик по кнопке «Загрузить файлы».
В момент клика создаем новый объект new formData() и добавляем в него данные из переменной files. С помощью formData() мы добьемся того, что отправляемые данные будут выглядеть, как если бы мы просто сабмитили форму в браузере.
Далее, из имеющихся данных формы создаем нестандартный AJAX запрос, в котором передаем файлы в стандартном для сервера формате: $_FILES.
Чтобы такой запрос состоялся, в jQuery нужно указать дополнительные AJAX параметры, поэтому привычная функция $.post() не подходит и мы используем более гибкий аналог: $.ajax().
Два важных дополнительных параметра нужно установить в false:
- processData
- Отключает обработку передаваемых данных. По умолчанию, например, для GET запросов jQuery собирает данные в строку запроса и добавляет эту строку в конец URL. Для POST данных делает другие преобразования. Нам любые изменения исходных данных будут мешать, поэтому отключаем эту опцию...
- contentType
- Отключает установку заголовка типа запроса. Дефолтная установка jQuery равна
"application/x-www-form-urlencoded". Такой заголовок не предусматривает отправку файлов. Если установить этот параметр в"multipart/form-data", PHP все равно не сможет распознать передаваемые данные и выведет предупреждение «Missing boundary in multipart/form-data»... В общем, проще всего отключить эту опция, тогда все работает!
// обработка и отправка AJAX запроса при клике на кнопку upload_files
jQuery('.upload_files').on( 'click', function( event ){
event.stopPropagation(); // остановка всех текущих JS событий
event.preventDefault(); // остановка дефолтного события для текущего элемента - клик для <a> тега
// ничего не делаем если files пустой
if( typeof files == 'undefined' ) return;
// создадим объект данных формы
var data = new FormData();
// заполняем объект данных файлами в подходящем для отправки формате
$.each( files, function( key, value ){
data.append( key, value );
});
// добавим переменную для идентификации запроса
data.append( 'my_file_upload', 1 );
// AJAX запрос
$.ajax({
url : './submit.php',
type : 'POST', // важно!
data : data,
cache : false,
dataType : 'json',
// отключаем обработку передаваемых данных, пусть передаются как есть
processData : false,
// отключаем установку заголовка типа запроса. Так jQuery скажет серверу что это строковой запрос
contentType : false,
// функция успешного ответа сервера
success : function( respond, status, jqXHR ){
// ОК - файлы загружены
if( typeof respond.error === 'undefined' ){
// выведем пути загруженных файлов в блок '.ajax-reply'
var files_path = respond.files;
var html = '';
$.each( files_path, function( key, val ){
html += val +'<br>';
} )
$('.ajax-reply').html( html );
}
// ошибка
else {
console.log('ОШИБКА: ' + respond.data );
}
},
// функция ошибки ответа сервера
error: function( jqXHR, status, errorThrown ){
console.log( 'ОШИБКА AJAX запроса: ' + status, jqXHR );
}
});
});
Шаг 3. Обрабатываем запрос: загружаем файлы на сервер
Теперь последний шаг: нужно обработать отправленный запрос.
Чтобы было наглядно обработаем запрос без дополнительных проверок для файлов, т.е. просто сохраним полученные файлы в нужную папку. Хотя, для безопасности, отправляемые файлы обязательно нужно проверять, хотя бы расширение (тип) файла...
Создадим файл submit.php с таким кодом (предполагается что submit.php лежит в той же папке, где и файл, с которого отправляется AJAX запрос):
<?php
if( isset( $_POST['my_file_upload'] ) ){
// ВАЖНО! тут должны быть все проверки безопасности передавемых файлов и вывести ошибки если нужно
$uploaddir = './uploads'; // . - текущая папка где находится submit.php
// cоздадим папку если её нет
if( ! is_dir( $uploaddir ) ) mkdir( $uploaddir, 0777 );
$files = $_FILES; // полученные файлы
$done_files = array();
// переместим файлы из временной директории в указанную
foreach( $files as $file ){
$file_name = $file['name'];
if( move_uploaded_file( $file['tmp_name'], "$uploaddir/$file_name" ) ){
$done_files[] = realpath( "$uploaddir/$file_name" );
}
}
$data = $done_files ? array('files' => $done_files ) : array('error' => 'Ошибка загрузки файлов.');
die( json_encode( $data ) );
}
Вот и все!
Важно! Этот код только показывает как получать и сохранять файлы. В действительности, вам нужно проверить форматы принимаемых файлов, их размер, транслитерировать кириллические названия и возможно делать какие-то еще проверки.
-
Чтобы не собирать по частям вышеописанный код загрузки, предлагаю его скачать.
Скопируйте содержимое архива на ваш php сервер, зайдите в главную паку (в браузере) и попробуйте загрузить файлы. Так, вы «в живую» увидите что и как работает.
Читайте также:
AJAX Загрузка файлов: пример для WordPress
Для WordPress обрабатывать AJAX запрос в разы проще, потому что есть готовые функции, например media_handle_upload().
Первый и второй шаг аналогичные, а в третьем шаге будем использовать встроенную функцию, которая добавит файл в медиатеку и привяжет его к текущему посту.
Чтобы код ниже начал работать, его нужно добавить в файл темы functions.php. Далее, создать страницу с ярлыком ajax_file_upload и зайти на эту страницу. В контенте вы увидите форму для добавления файла. Выбираете файлы и проверяете все ли загрузилось...
Это полноценный пример того, как безопасно загрузить файлы на сервер в среде WordPress.
