Загрузка файла

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

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

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

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

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

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

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

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

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

Табл. 1. Атрибуты поля для отправки файла
Атрибут Описание
accept Устанавливает фильтр на типы файлов, которые вы можете отправить через поле загрузки файлов.
size Ширина текстового поля, которое определяется числом символов моноширинного шрифта.
multiple Позволяет выбирать и загружать сразу несколько файлов.
name Имя поля, используется для его идентификации обработчиком формы.

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

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

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

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

Хотя можно установить ширину поля через атрибут 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. Загрузка фотографий

       

Загрузите ваши фотографии на сервер

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

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

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

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

Источник

Стилизация Input File

Сегодня будем стилизовать input type file. Т.к. стилизация тесно связана с обработкой input file на фронтенде, мы так же рассмотрим, как обработать выбранный файл и отправить на сервер. Скрипт будет работать для множества форм с возможностью не только загрузить файл при клике на кнопку, но так же перетаскиванием файла (drag-and-drop) в область загрузки. Если вам не нужен тот или иной функционал, вы легко сможете удалить часть кода.

1. Стилизация input type file

1.1 Кнопка «Прикрепить файл» — HTML, CSS

Сначала нам необходимо создать html-разметку.

  • multiple — данный атрибут необходим, если вы хотите разрешить отправку более одного файла;
  • accept — в данный атрибут запишите типы файлов (MIME-типы), которые разрешены для выбора.
 

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

.upload-file__input < opacity: 0; position: absolute; z-index: -1; overflow: hidden; width: 0.4px; height: 0.4px; >.upload-file__label < display: flex; justify-content: center; align-items: center; max-width: 240px; border: 2px dashed #150B22; padding: 9px 49px; border-radius: 6px; cursor: pointer; >.upload-file__icon < width: 30px; height: auto; margin-right: 11px; >.upload-file__label .upload-file__text, .upload-file__label .upload-file__icon path < transition: .25s ease; >.upload-file__label:hover .upload-file__text < color: #58862D; >.upload-file__label:hover .upload-file__icon path < fill: #58862D; >.upload-file__label:hover

1.2 Кнопка «Прикрепить файл» — JavaScript

document.addEventListener("DOMContentLoaded", () => < const forms = document.querySelectorAll("form"); const inputFile = document.querySelectorAll(".upload-file__input"); /////////// Кнопка «Прикрепить файл» /////////// inputFile.forEach(function(el) < let textSelector = document.querySelector(".upload-file__text"); let fileList; // Событие выбора файла(ов) el.addEventListener("change", function (e) < // создаём массив файлов fileList = []; for (let i = 0; i < el.files.length; i++) < fileList.push(el.files[i]); >// вызов функции для каждого файла fileList.forEach(file => < uploadFile(file); >); >); // Проверяем размер файлов и выводим название const uploadFile = (file) => < // файла 5 * 1024 * 1024) < alert("Файл должен быть не более 5 МБ."); return; >// Показ загружаемых файлов if (file && file.length > 1) < if ( file.length файла`; > if ( file.length > 4 ) < textSelector.textContent = `Выбрано $файлов`; > > else < textSelector.textContent = file.name; >> >); // Отправка формы на сервер const postData = async (url, fData) => < // имеет асинхронные операции // начало отправки // здесь можно оповестить пользователя о начале отправки // ждём ответ, только тогда наш код пойдёт дальше let fetchResponse = await fetch(url, < method: "POST", body: fData >); // ждём окончания операции return await fetchResponse.text(); >; if (forms) < forms.forEach(el => < el.addEventListener("submit", function (e) < e.preventDefault(); // создание объекта FormData let fData = new FormData(this); // Добавление файлов input type file let file = el.querySelector(".upload-file__input"); for (let i = 0; i < (file.files.length); i++) < fData.append("files[]", file.files[i]); // добавляем файлы в объект FormData() >// Отправка на сервер postData("./mail.php", fData) .then(fetchResponse => < console.log("Данные успешно отправлены!"); console.log(fetchResponse); >) .catch(function (error) < console.log("Ошибка!"); console.log(error); >); >); >); >; >);

2. Drag-and-drop загрузка файлов

Структура останется прежней, т.к. наша первоначальная разметка вполне подойдёт для создания drag-and-drop области.

2.1 Drag-and-drop — HTML, CSS

 

Улучшим юсабилити путём добавления стилей для drag-and-drop .

/* drag and drop - "hover" */ .upload-file__label.hover .upload-file__text < color: #ffb300; >.upload-file__label.hover .upload-file__icon path < fill: #ffb300; >.upload-file__label.hover < border: 2px dashed #ffb300; >/* drag and drop - ошибка */ .upload-file__label.error .upload-file__text < color: #d32f2f; >.upload-file__label.error .upload-file__icon path < fill: #d32f2f; >.upload-file__label.error < border: 2px dashed #d32f2f; >/* drag and drop - файл(ы) успешно перетянут(ы) */ .upload-file__label.drop .upload-file__text < color: #388e3c; >.upload-file__label.drop .upload-file__icon path < fill: #388e3c; >.upload-file__label.drop

2.2 Drag-and-drop загрузка файлов — JavaScript

Теперь напишем JavaScript для обработки событий перетаскивания файлов на веб-страницу. А уже в следующем пункте рассмотрим, как использовать кнопку добавления файла и область Drag-and-drop одновременно.

document.addEventListener("DOMContentLoaded", () => < const forms = document.querySelectorAll("form"); /////////// Загрузка файлов при помощи «Drag-and-drop» /////////// const dropZone = document.querySelector(".upload-file__label"); const dropZoneText = document.querySelector(".upload-file__text"); const maxFileSize = 5000000; // максимальный размер файла - 5 мб. let uploadDragFile = ""; // Проверка поддержки «Drag-and-drop» if (typeof (window.FileReader) == "undefined") < dropZone.textContent = "Drag&Drop Не поддерживается браузером!"; dropZone.classList.add("error"); >// Событие - перетаскивания файла dropZone.ondragover = function () < this.classList.add("hover"); return false; >; dropZone.ondragleave = function () < this.classList.remove("hover"); return false; >; let uploadDragFiles = ""; dropZone.ondrop = function (e) < // Событие - файл перетащили e.preventDefault(); this.classList.remove("hover"); this.classList.add("drop"); uploadDragFiles = e.dataTransfer.files; // Проверка размера файла if (uploadDragFiles[0].size >maxFileSize) < dropZoneText.textContent = "Размер превышает допустимое значение!"; this.addClass("error"); return false; >// Показ загружаемых файлов if (uploadDragFiles.length > 1) < if (uploadDragFiles.length файла`; > else < dropZoneText.textContent = `Выбрано $файлов`; > > else < dropZoneText.textContent = e.dataTransfer.files[0].name; >> // Отправка формы на сервер const postData = async (url, fData) => < // имеет асинхронные операции // начало отправки // здесь можно оповестить пользователя о начале отправки // ждём ответ, только тогда наш код пойдёт дальше let fetchResponse = await fetch(url, < method: "POST", body: fData >); // ждём окончания операции return await fetchResponse.text(); >; if (forms) < forms.forEach(el => < el.addEventListener("submit", function (e) < e.preventDefault(); // создание объекта FormData let fData = new FormData(this); // Добавление файлов input type file let file = el.querySelector(".upload-file__input"); for (let i = 0; i < (file.files.length); i++) < fData.append("files[]", file.files[i]); // добавляем файлы в объект FormData() >// Отправка на сервер postData("./mail.php", fData) .then(fetchResponse => < console.log("Данные успешно отправлены!"); console.log(fetchResponse); >) .catch(function (error) < console.log("Ошибка!"); console.log(error); >); >); >); >; >);

3. Совместное использование кнопки «Прикрепить файл» и Drag-and-drop

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

HTML-структура и CSS останутся без изменений. Объеденим JavaScript код.

document.addEventListener("DOMContentLoaded", () => < const forms = document.querySelectorAll("form"); for (let i = 1; i document.querySelectorAll(".upload-file__wrapper").forEach(function (current_item, index) < const inputFile = current_item.querySelector(".upload-file__input"); // создаём массив файлов let fileList = []; /////////// Кнопка «Прикрепить файл» /////////// let textSelector = current_item.querySelector(".upload-file__text"); // Событие выбора файла(ов) inputFile.addEventListener("change", function () < fileList.push(. inputFile.files); // console.log(inputFile.files); // вызов функции для каждого файла fileList.forEach(file =>< uploadFile(file); >); >); // Проверяем размер файлов и выводим название const uploadFile = (file) => < // размер файла 5 * 1024 * 1024) < alert("Файл должен быть не более 5 МБ."); return; >// Показ загружаемых файлов if (file && fileList.length > 1) < if (fileList.length файла`; > else < textSelector.textContent = `Выбрано $файлов`; > > else < textSelector.textContent = file.name; >fileList = []; > /////////// Загрузка файлов при помощи «Drag-and-drop» /////////// // const dropZones = document.querySelectorAll(".upload-file__label"); const dropZone = current_item.querySelector(".upload-file__label"); const dropZoneText = current_item.querySelector(".upload-file__text"); const maxFileSize = 5000000; // максимальный размер файла - 5 мб. // Проверка поддержки «Drag-and-drop» if (typeof (window.FileReader) == "undefined") < dropZone.textContent = "Drag&Drop Не поддерживается браузером!"; dropZone.classList.add("error"); >// Событие - перетаскивания файла dropZone.ondragover = function () < this.classList.add("hover"); return false; >; // Событие - отмена перетаскивания файла dropZone.ondragleave = function () < this.classList.remove("hover"); return false; >; // Событие - файл перетащили dropZone.addEventListener("drop", function (e) < e.preventDefault(); this.classList.remove("hover"); this.classList.add("drop"); uploadDragFiles = e.dataTransfer.files[0]; // один файл // Проверка размера файла if (uploadDragFiles.size >maxFileSize) < dropZoneText.textContent = "Размер превышает допустимое значение!"; this.addClass("error"); return false; >// Показ загружаемых файлов if (uploadDragFiles.length > 1) < if (uploadDragFiles.length файла`; > else < dropZoneText.textContent = `Выбрано $файлов`; > > else < dropZoneText.textContent = e.dataTransfer.files[0].name; >// добавляем файл в объект "uploadDragFiles_i" window["uploadDragFiles_"+index] = uploadDragFiles; >); >); // Отправка формы на сервер const postData = async (url, fData) => < // имеет асинхронные операции // начало отправки // здесь можно сообщить пользователю о начале отправки // ждём ответ, только тогда наш код пойдёт дальше let fetchResponse = await fetch(url, < method: "POST", body: fData >); // ждём окончания операции return await fetchResponse.text(); >; if (forms) < forms.forEach(el => < el.addEventListener("submit", function (e) < e.preventDefault(); // создание объекта FormData let fData = new FormData(this); // Добавление файлов input type file el.querySelectorAll(".upload-file__input").forEach((one_file, index) => < for (let i = 0; i < (one_file.files.length); i++) < fData.append("files[]", one_file.files[i]); // добавляем файлы, добавленные кнопкой >fData.append("files[]", window["uploadDragFiles_"+index]); // добавляем drug-&-drop файлы >); // Отправка на сервер postData("./mail-files.php", fData) .then(fetchResponse => < swal(< title: "Спасибо!", text: "Данные отправлены.", icon: "success", button: "Ok" >); // console.table("Данные успешно отправлены!", fetchResponse); el.reset(); // Очистка полей формы document.querySelectorAll(".upload-file__text").forEach(this_text => < this_text.textContent = "Выберите файл или перетащите в поле"; >); >) .catch(function (error) < swal(< title: error, icon: "error", button: "Ok" >); // console.table("Ошибка!", error); >); >); >); >; >);

4. Отправка множества input file multiple

Ранее мы успешно отправили все даннные формы (текстовые поля и файлы) на сервер.

Рассмотрим пример отправки multiple формы с множеством input file на почту.

 $file) < $path = __DIR__ . "/upload-files/" . $file; // путь загрузки файла if (copy($_FILES["files"]["tmp_name"][$key], $path)) < $file_attach[] = $path; >> > $c = true; foreach ($_POST as $key => $value) < if (is_array($value)) < $value = implode(", ", $value); >if ( $value != "" && $key != "project_name" && $key != "admin_email" && $key != "form_subject" && $key != "file_attach" ) < $message .= (($c = !$c) ? "" : "") . " $key $value "; > > $message = '  ' . $message . '
$project_name. $form_subject
'; // Отправляем сообщение if (empty($file_attach)) < $headers = "MIME-Version: 1.0" . PHP_EOL . "Content-Type: text/html; charset=utf-8" . PHP_EOL . "From: " . $project_name . " " . PHP_EOL . "Reply-To: " . $admin_email . "" . PHP_EOL; mail($admin_email, $form_subject, $message, $headers); # отправка текста > else < send_mail($admin_email, $form_subject, $message, $file_attach); # отправка файлов >// Функция для отправки сообщения с вложением function send_mail($to, $form_subject, $html, $paths) < $boundary = "--" . md5(uniqid(time())); // генерируем разделитель $headers = "MIME-Version: 1.0\n"; $headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\n"; $multipart = "--$boundary\n"; $multipart .= "Content-Type: text/html; charset='utf-8'\n"; $multipart .= "Content-Transfer-Encoding: Quot-Printed\n\n"; $multipart .= "$html\n\n"; $message_part = ""; foreach ($paths as $path) < $fp = fopen($path, "r"); if (!$fp) < echo "Файл $path не может быть прочитан"; exit(); >$file = fread($fp, filesize($path)); fclose($fp); $message_part .= "--$boundary\n"; $message_part .= "Content-Type: application/octet-stream\n"; $message_part .= "Content-Transfer-Encoding: base64\n"; $message_part .= "Content-Disposition: attachment; filename = \"" . $path . "\"\n\n"; $message_part .= chunk_split(base64_encode($file)) . "\n"; > $multipart .= $message_part . "--$boundary--\n"; if (!mail($to, $form_subject, $multipart, $headers)) < echo "К сожалению, письмо не отправлено"; exit(); >>

Надеюсь, вам понравилась данная информация. Если вам интересна тема web-разработки, то можете следить за выходом новых статей в Telegram.

Статьи из данной категории:

Источник

Читайте также:  placeholder
Оцените статью