Больше результатов...

Generic selectors
Только точные совпадения
Искать в заголовках
Искать в контенте
Post Type Selectors
Filter by Categories
FAQ
Hostenko
Вдохновение
Видеоуроки
Новости
Плагины
Темы
Уроки
Хаки

В этой заметке вы узнаете, как реализовать AJAX загрузку файлов на сервер с использованием jQuery. Это не так уж сложно!

Не знаю точно, но что-то мне подсказывает, что до появления jQuery загрузка файлов на сервер по AJAX технологии была чем-то очень непонятным, а значит крайне сложным. Но сегодня с появлением jQuery даже не обладающий опытом веб-мастер может сделать это без особых усилий. Однако, так или иначе, разобраться все же придется. И сейчас я попробую очень коротко и понятно объяснить вам, как это делается, а чтобы проще было воспринимать, урок содержит только нужное и разбит на шаги.

inet.ws - Powerful VPS Hosting in the USA, Canada, UK and DE!

Смотрите также:

Замечу заранее, что эта статья вряд ли поможет, если вы совсем плохо разбираетесь в jQuery и PHP, базовые знания обязательны. И, пожалуй, обязательно иметь хоть какой-то опыт в загрузке файлов (картинок) на сервер с обычной HTML формы, по крайней мере нужно представлять как это работает.

Ну, меньше слов, приступим!

Для начала предположим, что у нас есть такой HTML код: поле и кнопка загрузки:

<input type="file" multiple="multiple" accept=".txt,image/*">
<a href="#" class="submit button">Загрузить файлы</a>
<div class="ajax-respond"></div>

1. Получение данных файла из поля file

Первое что нам нужно сделать — это получить данные input поля при добавлении в него файла(ов). Для этого прикрепим к событию change свою функцию, которая установит данные файла:

// Переменная куда будут располагаться данные файлов

var files;

// Вешаем функцию на событие
// Получим данные файлов и добавим их в переменную

$('input[type=file]').change(function(){
	files = this.files;
});

Этот код сохранит данные поля type="file" в переменную files, с которой мы будем работать дальше.

2. Загружаем файлы по клику

Теперь, нам нужно повесить событие клика на кнопку "Загрузить файлы". Тут и будет посылаться AJAX запрос с данными файлов.

Создадим функцию, повесим ее на событие click и отправим AJAX запрос с данными файлов. Этот запрос отличается от обычного AJAX запроса, и тут не подходит обычная отправка POST данных:

// Вешаем функцию ан событие click и отправляем AJAX запрос с данными файлов

$('.submit.button').click(function( event ){
	event.stopPropagation(); // Остановка происходящего
	event.preventDefault();  // Полная остановка происходящего

	// Создадим данные формы и добавим в них данные файлов из files

	var data = new FormData();
	$.each( files, function( key, value ){
		data.append( key, value );
	});

	// Отправляем запрос

	$.ajax({
		url: './submit.php?uploadfiles',
		type: 'POST',
		data: data,
		cache: false,
		dataType: 'json',
		processData: false, // Не обрабатываем файлы (Don't process the files)
		contentType: false, // Так jQuery скажет серверу что это строковой запрос
		success: function( respond, textStatus, jqXHR ){

			// Если все ОК

			if( typeof respond.error === 'undefined' ){
				// Файлы успешно загружены, делаем что нибудь здесь

				// выведем пути к загруженным файлам в блок '.ajax-respond'

				var files_path = respond.files;
				var html = '';
				$.each( files_path, function( key, val ){ html += val +'<br>'; } )
				$('.ajax-respond').html( html );
			}
			else{
				console.log('ОШИБКИ ОТВЕТА сервера: ' + respond.error );
			}
		},
		error: function( jqXHR, textStatus, errorThrown ){
			console.log('ОШИБКИ AJAX запроса: ' + textStatus );
		}
	});

});

Что делает функция? Создает новый объект new formData(), добавляет в него данные файлов из массива files. Затем этот объект данных формы передается в AJAX запрос. 2 параметра нужно установить в false обязательно:

  • processData — потому что jQuery будет конвертировать массив files в строку, и сервер не сможет получить данные.
  • contentType — потому что дефолтные установки jQuery равны application/x-www-form-urlencoded, что не предусматривает отправку файлов. А еще, если установить этот параметр в multipart/form-data, похоже это ничего не даст.

3. Загрузка файлов на сервер

Чтобы наглядно показать, как обрабатывать отправленный во втором пункте запрос, приведу простой php-скрипт, без всяких проверок.

Создадим файл submit.php и добавим в него этот код (предполагается что submit.php лежит в той же папке, где и файл, с которого отправляется AJAX запрос):

<?php

// Здесь нужно сделать все проверки передаваемых файлов и вывести ошибки если нужно

// Переменная ответа

$data = array();

if( isset( $_GET['uploadfiles'] ) ){
	$error = false;
	$files = array();

	$uploaddir = './uploads/'; // . - текущая папка где находится submit.php

	// Создадим папку если её нет

	if( ! is_dir( $uploaddir ) ) mkdir( $uploaddir, 0777 );

	// переместим файлы из временной директории в указанную
	foreach( $_FILES as $file ){
		if( move_uploaded_file( $file['tmp_name'], $uploaddir . basename($file['name']) ) ){
			$files[] = realpath( $uploaddir . $file['name'] );
		}
		else{
			$error = true;
		}
	}

	$data = $error ? array('error' => 'Ошибка загрузки файлов.') : array('files' => $files );

	echo json_encode( $data );
}

Не используйте этот код напрямую! Пишите свой!

Вот и все.

Заключение

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

Чтобы не собирать весь вышеописанный код вручную, скачайте вот этот архив: ajax-file-upload.zip. Загрузите его содержимое на ваш php сервер, зайдите в паку из архива, и попробуйте загрузить файл. Вы увидите, как все это работает, сможете "пошаманить" над кодом и разобраться подробнее в реальных условиях...

Также, рекомендую к прочтению статью о базовых знаниях для создания AJAX запросов в WordPress:

Ajax в WordPress

Знания из этой статьи вам очень пригодятся при создании AJAX загрузки файлов под WordPress.

Автор: Тимур Камаев
inet.ws - Powerful VPS Hosting in the USA, Canada, UK and DE!
Алексей Шевченко
редактор wpcafe
Изучает сайтостроение с 2008 года. Практикующий вебмастер, специализирующий на создание сайтов на WordPress. Задать вопрос Алексею можно на https://profiles.wordpress.org/wpthemeus/

Комментарии к записи: 43

Максим:

Все это конечно интересно, но на HTML5 + последний jQuery не работает.
Выдает ОШИБКИ AJAX запроса: error :) до сервера дело не доходит.

Никита:

Смени тип json на html и все. Правда, не во всех браузерах будет работать..

Слава:

в ajax не силён, как мне второй параметр, вместе с data передать в submit.php

попробовал конструкцию
data : {‘data’:data, ‘id’:id}
не срабатывает

Fdnj:

Вставляете так же:
data.append( key, value );
в submit.php:
$var = $_POST[key]; // получаем value

Виталий:

У меня не работает
data.append(eventId, eventId);
$eventId=$_POST['eventId'];

Евгений:

data.append(‘eventId’, eventId);

ya:

зачем выкладывать нерабочий код?
ладно бы статья была старая, а тут изначально выложена бесполезный код…

каша:

все работает, с небольшими переделками у себя использовал

Игорь:

Спасибо! Всё работает. Отправлял файл аяксом первый раз, Ваша статья отлично помогла разобраться. Правда не получилось отправить в формате json, пришлось использовать xml. И да, было б хорошо вынести в саму статью о data.append( key, value ); т.к. голый файл редко надо отправлять. Для each надо добавить if, если файл является необязательным и не был выбран. И раз сайт называется «о WordPress за чашкой кофе», то правильно было б привести пример именно для WP, адрес wp-admin/admin-ajax.php, и обработка ответа от WP. Это рекомендации, а так еще раз спасибо за статью.

anton:

Господа, в наше время за такой «пример» вызывали на дуэль.
Код не работает.

Svmp:

И ты бы проиграл на дуэли, код работает

Артем:

Отличная статья. Впервые показали, пожалуй, самый простой способ загрузки файлов без перезагрузки страницы. Раньше для этих целей использовал невидимый тэг iframe , указывал его как target для формы, а потом уже из него возвращался в родительскую(текущую) форму. Приятно узнать, что это можно делать более простым способом через AJAX

TEster:

пиздюк!, я на твой нерабочий код пол дня потратил, рожу бы тебе набить

Svmp:

А ты не выражайся а учи JS и PHP

Anonimus:

А то, что на сервере принимает GET, в отправляется POST’ом тебя не смутило?

Евгений:

А почему должно смутить, что переменная отправленная GET параметром приходит вместе с POST запросом? Разберитесь сперва. Никто не запрещает использовать GET вместе с POST и в данном случае файлы передаются через POST а переменная uploadfiles в строке ‘./submit.php?uploadfiles’ GET параметром, если вы конечно понимаете, что переменная в адресе после вопросительного знака это всегда GET параметр.

Svmp:

Наверно библиотеку jQuery забыл подключить

srgTS:

Фильтруй речь! код рабочий и размещен здесь для ПРИМЕРА а если ты не хочешь разбираться сам, то вали на freelance.ru и там адекватные люди сделают все за тебя

ЖЖЖ:

Сложно, не понятно, криво. Есть библиотека autoload.js там все проще в разы…

ЖЖЖ:

upd. даже нельзя тут свой пост отредактировать… думал о другом… ajaxupload.3.5.js конечно же

Dima:

Спасибо, легко и просто.

Алекс:

Имея мозг, я им подумал), перед тем как тратить время.. А код случаем не для html5? Если так, то весь смысл теряется. Атрибуты странные в html. Без них работать будет?

Bobov:

Почти всё отлично работает. Два вопроса. 1. В директорию на сервере имена файлов переносятся нормально только если они в латинице. В кириллице пишется абракадабра. Причём пользователю возвращаются имена нормально. Как от этого избавиться? 2. Загружается только один последний выбранный файл. Как загрузить несколько?

Trionika:

Код из примера не работает.

Георгий:

Смешно, ajax отправляет данные POST запросом, а на сервере почему то GET

Евгений:

Присмотритесь:

url: ‘./submit.php?uploadfiles’,
type: ‘POST’,
data: data,

Здесь data передаётся методом POST и будет доступна через переменную $_POST, но так как это файлы, то $FILES, а uploadfiles указано GET параметром. Итого запрос идёт на ./submit.php с переменной $_GET[‘uploadfiles’] и переменными в $_POST / $_FILES переданные методом $_POST. Никто ж не запрещает одновременно передавать GET и POST данные.

Николай:

Спасибо! Все работает, у кого не выходит просто упускают что-то, в моем случае мне был нужен только один файл и я добавил его так:
var data = new FormData();
data.append(«name», $(«input[type=file]»)[0].files[0]);

и что бы не было ошибок обязательно использовать:
processData: false,
contentType: false,

Александр:

Подскажите как уже загруженные файлы отправлять на почту?

Сергей:

Спасибо. Всё работает, но пришлось удалить эти две строчки:
event.stopPropagation();
event.preventDefault();
иначе код дальше этих строчек не выполняется.
событие click считывается через метод on и действует на эту ссылку
Ответить
ну и данные в files считываю через метод on тоже
$(‘body’).on(‘change’, ‘#otvet-file’, function () {
files = this.files;
});
иначе в file ничего не считывает.
В моём случае поле input и ссылка подгружались в модальное окно посредством ajax.
Для других случаев не проверялось может код и работает без удаления тех двух строчек.

Rusic:

Класс ))

Rusic:

Можно было убрать вместо двух строчек, только верхнюю, вторая останавливает стандартную обработку формы

Rusic:

Хорошая статья, но я поправил чуток, думаю народу будет тоже интереснее не пути файлов видеть а картинки. Да и в форме accept расширить accept=»image/jpeg,image/png,image/gif»
подправить :
submit.php
$files[] = realpath( $uploaddir . $file[‘name’] );
на
$files[] = $uploaddir . $file[‘name’] ;

вместо:
$.each( files_path, function( key, val ){ html += val +»; } )
написать:
$.each( files_path, function( key, val ){ html += »; } )

само собой подправить чуток css
к примеру так
.admin .ajaxRespond {
display: -webkit-flex;
display: flex;
}
.admin .ajaxRespond-imgPreview {
width: 200px;
}

А так конечно все супер, я еще накинул создание превью и ресайз короче, столкнул дело с мертвой точки. Все хотел да никак. )

kotjarko:

Если «отправлять» без файлов — ошибка :) Лечится вот такой строчкой

event.preventDefault(); // Полная остановка происходящего
if (typeof files == ‘undefined’) return;

Спасибо за примерчик.

Kama:

Здравствуйте!

Я на правах автора статьи, прошу убрать nofollow со ссылок на мой сайт (wp-kama.ru), как это было изначально…

Также прошу, в конце статьи указать мое авторство, а то там почему-то «источник» указан, когда на сайте у меня нет статьи посвященной это теме.

Спасибо!

П.С. не нашел контактов, поэтому пиши суда.

Kama:

Мой предыдущий коммент проигнорирован и удален что ли?

WPcafe.org:

Все готово!

Kama:

Спасибо!

Павел:

Уважаемые!
Оберните код в форму, вместо click(function используйте submit(function т.е. событие на форму, а не на кнопку. Далее var form_data = new FormData($(this).get(0)); и передавайте в form_data все параметры формы, в том числе и прикрепленный файл.
$(‘#form’).submit(function(){
var form_data = new FormData($(this).get(0));
$.ajax({
url: ‘./submit.php?uploadfiles’,
type: ‘POST’,
data: form_data,
cache: false,
dataType: ‘json’,
processData: false, // Не обрабатываем файлы (Don’t process the files)
contentType: false,
success: function(){}
}
на выходе получите и POST и FILE

Алексей:

Спасибо за код, не первый раз его использую. Но в последний раз почему то data.append( key, value ); никак работать не хочет. var data = new FormData();
$.each( files, function( key, value ){
console.log(key+’;’+value);
data.append( key, value );
});
console.log(data);
В консоль выводит все файлы — console.log(key+’;’+value); но вот data — пустой… ошибки js не выдает….

Алексей:

В общем получилось так, что изменил dataType: на HTML, внес небольший правки и заработало!

Mher:

Добрый вечер господа. Код у меня почему то не заработал. а именно

var data = new FormData();
$.each( files, function( key, value ){
data.append(key,value);
при console.log(data) пустой объект

Добавить комментарий