Как form отправить в файл

Обновлено: 06.07.2024

В этой главе речь пойдёт об отправке HTML-форм: с файлами и без, с дополнительными полями и так далее. Объекты FormData помогут нам с этим. Как вы, наверняка, догадались по его названию, это объект, представляющий данные HTML формы.

Если передать в конструктор элемент HTML-формы form , то создаваемый объект автоматически прочитает из неё поля.

Его особенность заключается в том, что методы для работы с сетью, например fetch , позволяют указать объект FormData в свойстве тела запроса body .

Он будет соответствующим образом закодирован и отправлен с заголовком Content-Type: form/multipart .

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

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

Давайте сначала отправим простую форму.

Как вы видите, код очень компактный:

Методы объекта FormData

С помощью указанных ниже методов мы можем изменять поля в объекте FormData :

  • formData.append(name, value) – добавляет к объекту поле с именем name и значением value ,
  • formData.append(name, blob, fileName) – добавляет поле, как будто в форме имеется элемент <input type="file"> , третий аргумент fileName устанавливает имя файла (не имя поля формы), как будто это имя из файловой системы пользователя,
  • formData.delete(name) – удаляет поле с заданным именем name ,
  • formData.get(name) – получает значение поля с именем name ,
  • formData.has(name) – если существует поле с именем name , то возвращает true , иначе false

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

Ещё существует метод set , его синтаксис такой же, как у append . Разница в том, что .set удаляет все уже имеющиеся поля с именем name и только затем добавляет новое. То есть этот метод гарантирует, что будет существовать только одно поле с именем name , в остальном он аналогичен .append :

  • formData.set(name, value) ,
  • formData.set(name, blob, fileName) .

Поля объекта formData можно перебирать, используя цикл for..of :

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

Объекты FormData всегда отсылаются с заголовком Content-Type: form/multipart , этот способ кодировки позволяет отсылать файлы. Таким образом, поля <input type="file"> тоже отправляются, как это и происходит в случае обычной формы.

Пример такой формы:

Отправка формы с Blob-данными

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

Кроме того, серверы часто настроены на приём именно форм, а не просто бинарных данных.

В примере ниже посылается изображение из <canvas> и ещё несколько полей, как форма, используя FormData :

Пожалуйста, обратите внимание на то, как добавляется изображение Blob :

Это как если бы в форме был элемент <input type="file" name="image"> и пользователь прикрепил бы файл с именем "image.jpg" (3й аргумент) и данными imageBlob (2й аргумент) из своей файловой системы.

Сервер прочитает и данные и файл, точно так же, как если бы это была обычная отправка формы.

Итого

Мы можем создать такой объект уже с данными, передав в конструктор HTML-форму – new FormData(form) , или же можно создать объект вообще без формы и затем добавить к нему поля с помощью методов:

Для того чтобы можно было загружать на сервер один или несколько файлов, в форме применяется специальное поле. В браузерах Firefox, IE и Opera такой элемент отображается как текстовое поле, рядом с которым располагается кнопка с надписью «Обзор. » (рис. 1). В Safari и Chrome доступна только кнопка «Выберите файл» (рис. 2).

Вид поля для загрузки файла в Firefox

Рис. 1. Вид поля для загрузки файла в Firefox

Загрузка файлов в Chrome

Рис. 2. Загрузка файлов в Chrome

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

Синтаксис поля для отправки файла следующий.

Прежде, чем использовать данное поле, в форме необходимо сделать следующее:

  1. задать метод отправки данных POST ( method="post" );
  2. установить у атрибута enctype значение multipart/form-data .

Форма для загрузки файла продемонстрирована в примере 1.

Пример 1. Создание поля для отправки файла

HTML5 IE Cr Op Sa Fx

Хотя можно установить ширину поля через атрибут size , в действительности ширина никак не влияет на результат работы формы. В браузерах Safari и Chrome этот атрибут вообще никакого воздействия не оказывает.

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

Если атрибут accept не указывать, тогда добавляются и загружаются файлы любого типа. Наличие accept позволяет ограничить выбор файла, что особенно важно, когда требуется загрузить только изображение или видео. В качестве значения выступает MIME-тип, несколько значений разделяются между собой запятой. Также можно использовать следующие ключевые слова:

  • audio/* — выбор музыкальных файлов любого типа;
  • image/* — графические файлы;
  • video/* — видеофайлы.

В табл. 2 показаны некоторые допустимые значения атрибута accept .

Табл. 2. Типы файлов
ЗначениеОписание
image/jpegТолько файлы в формате JPEG.
image/jpeg,image/pngТолько файлы в формате JPEG и PNG.
image/*Любые графические файлы.
image/*,video/*Любые графические и видеофайлы.

Использование дополнительных атрибутов показано в примере 2.

Пример 2. Загрузка фотографий

HTML5 IE 10+ Cr Op Sa Fx

Не все браузеры поддерживают новые атрибуты. IE полностью игнорирует multiple и accept , Safari не поддерживает accept , а Firefox не работает с MIME-типом, только с ключевыми словами. Поэтому в примере выше специально для Firefox установлено значение image/*,image/jpeg . Также учтите странную ошибку в Опере, она не допускает пробелы после запятой внутри accept .

Результат примера показан на рис. 3. Обратите внимание, что из-за наличия multiple несколько изменился вид поля.

Для загрузки на сервер одного или нескольких файлов вроде фотографий, документов и видео применяется специальное поле формы. В браузере IE такой элемент отображается как текстовое поле, рядом с которым располагается кнопка с надписью «Обзор. » (рис. 1). В Safari, Opera и Chrome доступна только кнопка «Выбрать файлы» (рис. 2), в Firefox это только кнопка «Обзор» (рис. 3).

Вид поля для загрузки файла в IE

Рис. 1. Вид поля для загрузки файла в IE

Загрузка файлов в Opera и Chrome

Рис. 2. Загрузка файлов в Opera и Chrome

Загрузка файлов в Firefox

Рис. 3. Загрузка файлов в Firefox

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

Синтаксис поля для отправки файла следующий.

Атрибуты перечислены в табл. 1.

Табл. 1. Атрибуты поля для отправки файла
Атрибут Описание
name Имя поля; используется для его идентификации обработчиком формы.
disabled Блокирует поле для отправки файлов.
form Идентификатор формы для связывания поля с элементом <form> .
type Для загрузки файлов значение должно быть file .
accept Устанавливает фильтр на типы файлов, которые вы можете открыть через поле загрузки файлов.
autofocus Поле получает фокус после загрузки документа.
required Указывает, что поле является обязательным для заполнения.
multiple Позволяет выбирать и загружать сразу несколько файлов.

Для отправки файлов в форме необходимо сделать следующее:

  1. задать метод отправки данных POST ( method="post" );
  2. установить у атрибута enctype значение multipart/form-data .

Кроме того, данное поле нельзя вставлять внутрь ссылки и кнопки.

Форма для загрузки файла продемонстрирована в примере 1.

Пример 1. Создание поля для отправки файла

Атрибут multiple важен, он позволяет не ограничиваться одним файлом для выбора, а указать сразу несколько файлов для одновременной загрузки (пример 2). Выбор нескольких файлов происходит с помощью мыши или клавиатуры через клавиши Ctrl и Shift .

Пример 2. Загрузка нескольких файлов

Если атрибут accept не указывать, тогда добавляются и загружаются файлы любого типа. Наличие accept позволяет ограничить выбор файла, что особенно важно, когда требуется загрузить только изображение или видео. В качестве значения выступает MIME-тип, несколько значений разделяются между собой запятой. Также можно использовать следующие ключевые слова:

  • audio/* — выбор музыкальных файлов любого типа;
  • image/* — графические файлы;
  • video/* — видеофайлы.

В табл. 2 показаны некоторые допустимые значения атрибута accept .

Табл. 2. Типы файлов
Значение Описание
image/jpeg Только файлы в формате JPEG.
image/jpeg,image/png Только файлы в формате JPEG и PNG.
image/* Любые графические файлы.
image/*,video/* Любые графические и видеофайлы.

Использование дополнительных атрибутов показано в примере 3.

Пример 3. Загрузка фотографий

Ниже представлены два варианта скрипта отправки данных с сайта на почту: с Javascript (Ajax) и без.

  1. PHP вынесен в отдельный файл
  2. при нажатии клавиши F5 форма не будет отправлена снова
  3. после отправки формы страница не будет перезагружена

Файл contacts.html

Файл contacts.php

2. Форма связи в одном файле

Рекомендации к скрипту отправки файлов на почту

Создать правило в Яндекс.Почте, чтобы письма не уходили в СПАМ

Скорее всего письма будут падать в СПАМ папку, поэтому для них нужно создать правило. Скажем, так это делается в Яндекс.Почте:

Если на хостингах выключена функция mail() (галка может именоваться "sendmail_from"), то скрпт работать не будет. Так как по факту email отправляется с электронного ящика хостинга.

127 комментариев:

Спасибо заранее =) Владимир Телевной P.S.
Желательно чтоб было реализовано все на столько же просто как данная форма. Т.к. я не просто ноль, а ноль с большим минусом. И мои знания ограничиваются копировал-вставил. NMitra Здравствуйте, я боялась этого вопроса )) Пока нет времени написать полноценное решение и толком разобраться. Нужно объединить:

$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"_1_$boundary\"";

$message="
--_1_$boundary
Content-Type: multipart/alternative; boundary=\"_2_$boundary\"

--_2_$boundary
Content-Type: text/plain; charset=\"utf-8\"
Content-Transfer-Encoding: 7bit

--_2_$boundary--
--_1_$boundary
Content-Type: \"$filetype\"; name=\"$filename\"
Content-Transfer-Encoding: base64
Content-Disposition: attachment

mail($to, $subject, $message, $headers);

>
?> Анонимный Подскажите как сделать чтобы можно было прикрепить несколько файлов? Анонимный Подскажите как добавить защиту от спама? NMitra Фильтра по IP в большинстве случаев хватает. Чтобы его узнать, следует строку

Затем при обнаружении IP, рассылающего спам

mail($to, $subject, $message, $headers);

килобайт (КБ) = 1024 байта
мегабайт(МБ) = 1024 килобайта

10 МБ = 10485760 байт (тут всё сравнительно верно)

У меня с ними тоже Яндекс режет письма. Александр Стрельченко Здравствуйте еще раз.
Заголовки эти сразу удалил и не использовал.

Оставил только эти два:

$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n";

Я делал прикрепление одного файла, а в html мой инпут имел такой вид:

Убрав скобки массива "[]" все заработало, при этом письма доходят моментально и с вложением.

.htaccess удалять не стоит. Смотрите какое именно правило не даёт работать форме. Его (правило) можно ограничить одной страницей, расширением файла и т.п.

Читайте также: