Загрузка файлов без перезагрузки страницы
На курсах мы рассказываем, что файлы загружаются на сервер по протоколу POST, причем происходит перезагрузка страницы после отправки формы (у формы есть атрибут action, если он не заполнен форма будет отправлена на адрес текущей страницы).
Задача состояла в том, чтобы сделать интерфейс загрузки файлов более удобным: Т.е. чтобы не было необходимости перезагружать страницу. Например, так это выглядит в контакте или подобным образом, при этом было решено не использовать flash.
Какие есть варианты? Можно использовать flash. Но мы решили не делать этого. Только php, JavaScript. Поэтому мы обратились к старому проверенному способу, который работает во всех браузерах без особых нареканий - фрейм (frame).
Как мы рассказываем на курсе веб-дизайна, в свое время фреймы довольно часто использовались для создания сайтов и веб-приложений, к примеру, phpMyAdmin до сих пор использует фреймы..
Так вот, для того чтобы загрузить файл на сервер, мы берем то что у нас уже есть - это форма, осталось добавить фрейм и немного JavaScript.
<form action="upload.php" target="upload" method="POST" enctype="multipart/form-data">
<input type="file" name="files[]" multiple >
</form>
,и где-то вне формы разместим frame:
И так, по порядку:
- У формы атрибут action показывает на тот файл в котором будет производиться обработка загружаемых файлов, т.е. работа с массивом $_FILES
- Атрибут target указывает на frame!
- input для выбора имени файла имеет параметр multiple, это позволяет выбирать не один файл, а сразу много, при этом параметр name будет выглядеть как [имя][].
Таким образом, по сути страница перезагружается, но только во фрейме. Что нам и надо.
В файле upload.php можно разместить такой код:
if(count($_FILES["files_1"])>0) foreach ($_FILES["files_1"]["tmp_name"] as $key => $error) if($error == UPLOAD_ERR_OK and $_FILES["files_1"]["tmp_name"][$key]!='') $tmp_name = $_FILES["files_1"]["tmp_name"][$key];//временное имя файла
$name = $_FILES["files_1"]["name"][$key];
$mtime = time();
$type_t = pathinfo($name);
$type = $type_t['extension'];
$name_file = $mtime.$key.'.'.$type; //новое имя файла
move_uploaded_file($tmp_name, $_SERVER['DOCUMENT_ROOT'].'/files/'.$name_file); //перемещаем файл
>
>
>
После загрузки файлов генерируем и выводим при помощи echo JavaScript код window.parent.function(), где function() - акая то функция, которая например, при помощи ajax формирует новый список файлов для отображения на основной странице.
Итак, получается что мы из формы передали данные во фрейм, на сервере обработали данные отдали ответ, который как раз и пришел во фрейм (ведь он то перезагрузился в отличии от остальной части старницы) и получили результат, просто и надежно.
Если Вас заинтересовала данная статья и Вы бы хотели научиться делать проекты такого уровня, то приглашаем Вас на наши курсы, которые будет вести Андрейчиков Юрий Сергеевич, сертифицированный программист 1с-битрикс.
Дата: 9 марта 201153479 35
В прошлых статьях я уже рассказывал Вам о том, как загрузить файлы на сервер. О них можно почитать здесь и здесь. В этой же статье я постараюсь рассказать, как загрузить файл на сервер без перезагрузки страницы.
Обращаю Ваше внимание на фразу «без перезагрузки страницы» - это не с помощью AJAX. Так как Вы должны четко понимать, что с помощью AJAX не возможно загрузить файл на сервер.
О том, как это сделать, я постараюсь рассказать в этой статье!
Итак, для того чтобы организовать такую загрузку файла, нам понадобится: невидимый фрейм, атрибут формы target и javascript.
Итак, давайте создадим страничку upload.html с нашей формой для загрузки файла и невидимый фрейм:
Как видите, это обычная форма для загрузки файла на сервер, только в параметре target указан id скрытого фрейма! Также в коде есть контейнер для вывода результата загрузки.
Теперь, если пользователь выберет файл и нажмет кнопку «Загрузить», файл будет отправлен серверу, а результат будет загружен в скрытый iframe. После того, как данные будут переданы в iframe, необходимо их передать на основную страницу.
Для этого в ответ сервера, необходимо вставить javascript код, который будет вызывать js-функцию, объявленную на основной странице и в качестве параметров, передавать ей результат выполнения запроса.
Для этого добавим в файл upload.html следующий javascript-код:
Функция hideBtn() вызывается в момент отправки файла и служит для информирования пользователя о начале загрузки, а также скрывает кнопку «Загрузить», для того, чтобы пока не пришел ответ с сервера, пользователь не смог загрузить новый файл.
Теперь давайте создадим файл upload.php, которому будет передаваться файл:
Здесь нет ничего нового! Обо всем этом я рассказывал в предыдущих постах. Единственное, что я добавил — это формирование строки, которая содержит обычный JavaScript код. Когда ответ сервера будет загружет во фрейм, код будет автоматически выполнен.
Для удобства использования, я создаю объект JavaScript
названия свойств которого будут совпадать с ключами массива.
Если возникает ошибка, то этот объект будет содержать следующее значение:
Если ошибок нет, то этот объект будет содержать информацию о загруженном файле.
На курсах мы рассказываем, что файлы загружаются на сервер по протоколу POST, причем происходит перезагрузка страницы после отправки формы (у формы есть атрибут action, если он не заполнен форма будет отправлена на адрес текущей страницы).
Задача состояла в том, чтобы сделать интерфейс загрузки файлов более удобным: Т.е. чтобы не было необходимости перезагружать страницу. Например, так это выглядит в контакте или подобным образом, при этом было решено не использовать flash.
Какие есть варианты? Можно использовать flash. Но мы решили не делать этого. Только php, JavaScript. Поэтому мы обратились к старому проверенному способу, который работает во всех браузерах без особых нареканий - фрейм (frame).
Как мы рассказываем на курсе веб-дизайна, в свое время фреймы довольно часто использовались для создания сайтов и веб-приложений, к примеру, phpMyAdmin до сих пор использует фреймы..
Так вот, для того чтобы загрузить файл на сервер, мы берем то что у нас уже есть - это форма, осталось добавить фрейм и немного JavaScript.
<form action="upload.php" target="upload" method="POST" enctype="multipart/form-data">
<input type="file" name="files[]" multiple >
</form>
,и где-то вне формы разместим frame:
И так, по порядку:
- У формы атрибут action показывает на тот файл в котором будет производиться обработка загружаемых файлов, т.е. работа с массивом $_FILES
- Атрибут target указывает на frame!
- input для выбора имени файла имеет параметр multiple, это позволяет выбирать не один файл, а сразу много, при этом параметр name будет выглядеть как [имя][].
Таким образом, по сути страница перезагружается, но только во фрейме. Что нам и надо.
В файле upload.php можно разместить такой код:
if(count($_FILES["files_1"])>0) foreach ($_FILES["files_1"]["tmp_name"] as $key => $error) if($error == UPLOAD_ERR_OK and $_FILES["files_1"]["tmp_name"][$key]!='') $tmp_name = $_FILES["files_1"]["tmp_name"][$key];//временное имя файла
$name = $_FILES["files_1"]["name"][$key];
$mtime = time();
$type_t = pathinfo($name);
$type = $type_t['extension'];
$name_file = $mtime.$key.'.'.$type; //новое имя файла
move_uploaded_file($tmp_name, $_SERVER['DOCUMENT_ROOT'].'/files/'.$name_file); //перемещаем файл
>
>
>
После загрузки файлов генерируем и выводим при помощи echo JavaScript код window.parent.function(), где function() - акая то функция, которая например, при помощи ajax формирует новый список файлов для отображения на основной странице.
Итак, получается что мы из формы передали данные во фрейм, на сервере обработали данные отдали ответ, который как раз и пришел во фрейм (ведь он то перезагрузился в отличии от остальной части старницы) и получили результат, просто и надежно.
Если Вас заинтересовала данная статья и Вы бы хотели научиться делать проекты такого уровня, то приглашаем Вас на наши курсы, которые будет вести Андрейчиков Юрий Сергеевич, сертифицированный программист 1с-битрикс.
В этой заметке вы узнаете, как реализовать AJAX загрузку файлов на сервер с использованием jQuery. Это не так уж сложно!
Не знаю точно, но что-то мне подсказывает, что до появления jQuery загрузка файлов на сервер по AJAX технологии была чем-то очень непонятным, а значит крайне сложным. Но сегодня с появлением jQuery даже не обладающий опытом веб-мастер может сделать это без особых усилий. Однако, так или иначе, разобраться все же придется. И сейчас я попробую очень коротко и понятно объяснить вам, как это делается, а чтобы проще было воспринимать, урок содержит только нужное и разбит на шаги.
Замечу заранее, что эта статья вряд ли поможет, если вы совсем плохо разбираетесь в jQuery и PHP, базовые знания обязательны. И, пожалуй, обязательно иметь хоть какой-то опыт в загрузке файлов (картинок) на сервер с обычной HTML формы, по крайней мере нужно представлять как это работает.
Ну, меньше слов, приступим!
Для начала предположим, что у нас есть такой HTML код: поле и кнопка загрузки:
1. Получение данных файла из поля file
Первое что нам нужно сделать — это получить данные input поля при добавлении в него файла(ов). Для этого прикрепим к событию change свою функцию, которая установит данные файла:
Этот код сохранит данные поля type="file" в переменную files , с которой мы будем работать дальше.
2. Загружаем файлы по клику
Теперь, нам нужно повесить событие клика на кнопку " Загрузить файлы ". Тут и будет посылаться AJAX запрос с данными файлов.
Создадим функцию, повесим ее на событие click и отправим AJAX запрос с данными файлов. Этот запрос отличается от обычного AJAX запроса, и тут не подходит обычная отправка POST данных:
Что делает функция? Создает новый объект 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 запрос):
Не используйте этот код напрямую! Пишите свой!
Заключение
Эта статья только обучает технологии загрузки файлов с помощью AJAX. В действительности, вам нужно проверить форматы принимаемых файлов, их размер и уведомить пользователей, что произошла загрузка файла.
Чтобы не собирать весь вышеописанный код вручную, скачайте вот этот архив: ajax-file-upload.zip . Загрузите его содержимое на ваш php сервер, зайдите в паку из архива, и попробуйте загрузить файл. Вы увидите, как все это работает, сможете "пошаманить" над кодом и разобраться подробнее в реальных условиях.
Также, рекомендую к прочтению статью о базовых знаниях для создания AJAX запросов в WordPress:
Знания из этой статьи вам очень пригодятся при создании AJAX загрузки файлов под WordPress.
В прошлой статье, мы пробежались по нескольким основным методам для получения данных и их дальнейшей передаче AJAX-запросом. Теперь пришло время поговорить о том, как же можно загружать файлы с помощью AJAX. Еще до недавнего времени, способов загружать файлы без перезагрузки самой страницы, было не так уж и много (скрытый iframe, Flash). Они и сейчас используются по причине того, что еще остаются пользователи со старыми версиями браузеров, которых не коснулся прогресс. Но оглядываться назад не будем, посему шагаем в ногу со временем.
Рассмотрим, на мой взгляд, один из самых удобных способов для работы с файлами (и не только) - объект FormData. Пусть будет такая простенькая форма, для загрузки аватара пользователя:
HTML (файл index.html)
Перейдем к JS-части. С полем "Ф.И.О" сложностей не будет и его используем только для наглядности того, что вместе с файлом, мы можем отправлять любые другие данные.
jQuery (файл script.js)
(*)Обратите внимание на то, что передаем форму не объектом jQuery, а DOM-элемент
PHP-обработчик (файл handler.php)
Если всё было сделано правильно, то на экране нам выведится информация в таком виде:
Ясное дело, что выводить эту информацию нам не потребуется, а нужно будет сохранять файл на сервере, указав ему место "постоянной прописки" ;). Как загружать/сохранять файлы средствами php, я описывать тут не буду, т.к. тема не маленькая и ей можно посветить отдельную статью. Для самых нетерпеливых, могу дать пару намёков - используем: move_uploaded_file(), getimagesize(), Fileinfo и другие полезные функции. И не забывайте, что очень желательно задавать файлам уникальные имена, т.к. при совпадении имён и расширений, старый файл будет попросту перезаписан новым.
"Замечтательно! - скажите вы. - А как же быть, если нужно загрузить несколько файлов одновременно?" Ничего сверхъестественного и существует несколько способов реализации:
- Используем атрибут multiple (в нашем случае, позволяет для одного поля input указывать несколько файлов). Добавляем этот атрибут в наше поле и изменяем его имя, добавив квадратные скобки "[]". Это укажет, что мы передаем массив данных из этого поля: Способ хороший, но к сожалению не все браузеры с ним дружат.
- Заранее подготовить несколько полей, которым так же можно указать одинаковые имена массивом: Это уже кроссбраузерный вариант, но и он имеет маленькие недостатки при определённых обстоятельствах. К примеру, мы создали два поля, а пользователю необходимо загрузить три и более файлов.
- Динамическое добавление полей. Тут мы создаем одно поле и добавляем какую-нибуть кнопку, по нажатию на которую, пользователь сможет добавлять необходимое кол-во дополнительный полей. Каким способом добавлять поля - дело вашего вкуса и фантазии. Можно заранее подготовить код поля в JS, присвоив его переменной, можно клонировать уже существующий элемент - clone() и т.д.
Во всех трёх вариантах, на стороне сервера, мы получим массив файлов и, как с любым другим массивом, обрабатываем его в цикле.
Ещё одним моментом, который сто́ит затронуть - это добавление файлов (и других данных) в FormData, если формы, как таковой, нету или данные берутся из других источников. Для этой задачи, будем использовать метод append(), который похож на jQuery-метод append(), но выполняет немного другой функционал. Синтаксис метода:
Где параметры: name Имя поля, данные которого передаются в параметре value. По сути, если мы взяли данные не из поля формы, у которого есть атрибут name, то мы этот name задаём сами. value Значение поля. Может быть типа Blob, File или string filename Необязательный параметр. Для типов Blob и File - имя файла, сообщаемое серверу
Возьмем нашу форму загрузки аватара без изменений и предположим, что мы хотим добавим к ней текущую дату. Теперь наш код должен выглядеть следующим образом:
Вуаля, собственно новые данные добавлены к набору передавемых на сервер. Наша дата будет в переменной $_POST['date_upl']. Для добавления еще одной и более пары "ключ - значение", используем ту же конструкцию. С файлами дело обстоит так же, но нужно учитывать, что значением является DOM-элемент, а не объект jQuery. И напомню, что абсолютно все данные, приходящие от клиента , должны в обязательном порядке подвергаться проверке, фильтрации, валидации и т.д.!
На этом можно было бы поставить многоточие, но не точку, т.к. тема обширна и всегда будут обстоятельства, которые потребуют нестандартных путей решения. Осталось еще пара небольших вопросов, которые относятся к данной теме, но я решил их вынести в отдельные статьи. Непосредственно по теме загрузки файлов - создание прогрессбара (индикатора выполнения загрузки на сервер) и Ajax на чистом (нативном) JS, без использования фреймворков.
Читайте также: