базовый курс

ГРУППА КУРСА

Отправка файла в AJAX

Отправка формы с файлом

В прошлой теме я рассказывал, как отправить данные. А в этой теме я расскажу, как делается отправка файла в AJAX. Для начала рассмотрим ситуацию, когда файл является частью формы. Создадим форму, содержащую поле для отправки файла:

+
8
9
10
11
12
<form>
  <input type="text" name="inform">
  <input type="file" name="image">
  <input type="button" name="send" value="Отправить">
</form>

Данные будем отправлять с помощью объекта FormData. Напомню, что этот объект не использует данные, введённые пользователем в форму. Их придётся переписывать в объект. Но при отправке файла это оптимальный вариант.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var form = document.querySelector('form');

form.send.onclick = function ()
  {
  var sendForm = new FormData();
  sendForm.append('inf', form.inf.value);
  sendForm.append('image', form.image.files[0]);
  
  var xhr = new XMLHttpRequest();
  xhr.open('POST','takeform.php');
  xhr.onreadystatechange = function ()
    {
    if (xhr.readyState == 4)
      {
      var an = xhr.responseText;
      if (an)
      console.log(an);
      }
    };
  xhr.send(sendForm);
  };

Это обычная реализация технологии AJAX. То, что относится к отправке файла, содержится в строке 20. Поле для файла я назвал image. DOM-объект этого поля имеет свойство files. Оно содержит псевдомассив с файлами, которые выбрал пользователь. В нашем примере пользователь может выбрать только один файл. Мы записываем его в объект FormData и задаём параметру имя image. В объекте есть ещё один параметр, в который записаны данные из другого поля формы.

Серверная часть ничем не отличается от обычного приёма файла. Она рассмотрена в учебнике PHP. Скрипт получает файл в массиве $_FILES, а остальные данные в массиве $_POST.

Если тегу <input>, отправляющему файл, указан атрибут multiple, то пользователь может выбрать несколько файлов.

10
<input type="file" name="image" multiple>

Все файлы находятся в свойстве files DOM-объекта <input>. Их нужно записать в объект FormData по отдельности.

20
21
22
23
24
var images = form.image.files;
for (var i=0; i<images.length; i++)
  {
  sendForm.append('image' + i, images[i]);
  }

Свойство files я записал в переменную images, чтобы к нему было удобнее обращаться. Далее идёт цикл, в котором каждый файл помещается в объект FormData. Имена параметров должны отличаться, поэтому к имени параметра добавляется значение переменной i. Имена получаются: image0, image1 и так далее. С такими именами параметры получит сервер.

Отправка файла при выборе

Иногда нужно сделать загрузку файла на сервер, без других данных. Тогда на странице можно разместить только тег <input> без формы и кнопки отправки. На <input> ставится обработчик события Change. В обработчике происходит отправка файла. Когда пользователь выбирает файл, он сразу отправляется на сервер.

К полю для выбора файла трудно применять стили. Поэтому обычно делают так: тег <input> помещают в тег <label>. Тег <input> делают невидимым, а к <label> применяют нужные стили. Пример:

Стиль:

7
8
9
10
11
12
13
14
15
16
17
label
  {
  font: 20px Arial, sans-serif;
  color: #4023AA;
  cursor: pointer;
  }
label input
  {
  width: 1px;
  opacity: 0;
  }

HTML код:

27
28
29
30
<label>
  Выбрать файл
  <input type="file">
</label>

На <input> нужно поставить обработчик события Change, чтобы файл отправлялся сразу при выборе.

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
var input = document.querySelector('label input');

input.onchange = function ()
  {
  var sendForm = new FormData();
  sendForm.append('image', input.files[0]);
  
  var xhr = new XMLHttpRequest();
  xhr.open('POST','takefile.php');
  xhr.onreadystatechange = function ()
    {
    if (xhr.readyState == 4)
      {
      var an = xhr.responseText;
      if (an)
      console.log(an);
      }
    }
  xhr.send(sendForm);
  };

Скрипт практически такой же, как при отправке формы. В объект FormData можно добавить какие-то данные о пользователе и отправляемом файле. В ответ сервера желательно поместить информацию о том, успешно ли загружен файл. А в скрипте обработать эту информацию.