Как form отправить в файл
В этой главе речь пойдёт об отправке 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).
Рис. 1. Вид поля для загрузки файла в Firefox
Рис. 2. Загрузка файлов в Chrome
При нажатии на кнопку открывается окно для выбора файла, где можно указать, какой файл пользователь желает использовать.
Синтаксис поля для отправки файла следующий.
Прежде, чем использовать данное поле, в форме необходимо сделать следующее:
- задать метод отправки данных POST ( method="post" );
- установить у атрибута enctype значение multipart/form-data .
Форма для загрузки файла продемонстрирована в примере 1.
Пример 1. Создание поля для отправки файла
HTML5 IE Cr Op Sa Fx
Хотя можно установить ширину поля через атрибут size , в действительности ширина никак не влияет на результат работы формы. В браузерах Safari и Chrome этот атрибут вообще никакого воздействия не оказывает.
Атрибут multiple более важен, он позволяет не ограничиваться одним файлом для выбора, а указать их сразу несколько для одновременной загрузки.
Если атрибут accept не указывать, тогда добавляются и загружаются файлы любого типа. Наличие accept позволяет ограничить выбор файла, что особенно важно, когда требуется загрузить только изображение или видео. В качестве значения выступает MIME-тип, несколько значений разделяются между собой запятой. Также можно использовать следующие ключевые слова:
- audio/* — выбор музыкальных файлов любого типа;
- image/* — графические файлы;
- video/* — видеофайлы.
В табл. 2 показаны некоторые допустимые значения атрибута accept .
Значение | Описание |
---|---|
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).
Рис. 1. Вид поля для загрузки файла в IE
Рис. 2. Загрузка файлов в Opera и Chrome
Рис. 3. Загрузка файлов в Firefox
При нажатии на кнопку открывается окно для выбора файла, где можно указать, какой файл пользователь желает использовать.
Синтаксис поля для отправки файла следующий.
Атрибуты перечислены в табл. 1.
Атрибут | Описание |
---|---|
name | Имя поля; используется для его идентификации обработчиком формы. |
disabled | Блокирует поле для отправки файлов. |
form | Идентификатор формы для связывания поля с элементом <form> . |
type | Для загрузки файлов значение должно быть file . |
accept | Устанавливает фильтр на типы файлов, которые вы можете открыть через поле загрузки файлов. |
autofocus | Поле получает фокус после загрузки документа. |
required | Указывает, что поле является обязательным для заполнения. |
multiple | Позволяет выбирать и загружать сразу несколько файлов. |
Для отправки файлов в форме необходимо сделать следующее:
- задать метод отправки данных POST ( method="post" );
- установить у атрибута enctype значение multipart/form-data .
Кроме того, данное поле нельзя вставлять внутрь ссылки и кнопки.
Форма для загрузки файла продемонстрирована в примере 1.
Пример 1. Создание поля для отправки файла
Атрибут multiple важен, он позволяет не ограничиваться одним файлом для выбора, а указать сразу несколько файлов для одновременной загрузки (пример 2). Выбор нескольких файлов происходит с помощью мыши или клавиатуры через клавиши Ctrl и Shift .
Пример 2. Загрузка нескольких файлов
Если атрибут accept не указывать, тогда добавляются и загружаются файлы любого типа. Наличие accept позволяет ограничить выбор файла, что особенно важно, когда требуется загрузить только изображение или видео. В качестве значения выступает MIME-тип, несколько значений разделяются между собой запятой. Также можно использовать следующие ключевые слова:
- audio/* — выбор музыкальных файлов любого типа;
- image/* — графические файлы;
- video/* — видеофайлы.
В табл. 2 показаны некоторые допустимые значения атрибута accept .
Значение | Описание |
---|---|
image/jpeg | Только файлы в формате JPEG. |
image/jpeg,image/png | Только файлы в формате JPEG и PNG. |
image/* | Любые графические файлы. |
image/*,video/* | Любые графические и видеофайлы. |
Использование дополнительных атрибутов показано в примере 3.
Пример 3. Загрузка фотографий
Ниже представлены два варианта скрипта отправки данных с сайта на почту: с Javascript (Ajax) и без.
- PHP вынесен в отдельный файл
- при нажатии клавиши F5 форма не будет отправлена снова
- после отправки формы страница не будет перезагружена
Файл 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 удалять не стоит. Смотрите какое именно правило не даёт работать форме. Его (правило) можно ограничить одной страницей, расширением файла и т.п.
Читайте также: