При создании форм обратной связи часто возникает потребность в отправке файла. Например, мы хотим отправить рисунок, для заказа печати плакатов в копицентре. Помимо отправки, может еще потребоваться проверить файл на размер и формат. В нашем примере мы ограничим форматы только файлами изображений (png, jpg, jpeg, svg), а также можно задать максимальный размер 20 Мб (чтобы не перегружать сервер).
Полезные ссылки
Эта статья — четвертая из серии статей про формы обратной связи. В предыдущей статье реализовали отправку сообщения без перезагрузки страницы. Поэтому писать код будем на основе исходника из третьей статьи. Вам необходимо склонировать репозиторий:
git clone https://github.com/toni-wheel/youtube-responsive-contact-form-v3
Ссылки на предыдущие статьи:
- Форма обратной связи: пишем основу на HTML и CSS: https://codelab.pro/forma-obratnoj-svyazi-pishem-osnovu-na-html-i-css/
- Форма обратной связи: валидация формы на JS: https://codelab.pro/forma-obratnoj-svyazi-validacziya-formy-na-js/
- Форма обратной связи: отправка формы на почту без перезагрузки: https://codelab.pro/forma-obratnoj-svyazi-otpravka-formy-na-pochtu-bez-perezagruzki/
Разметка
Вся разметка находится в элементе с классом file-box:
<div class="file-box">
<div class="file__field">
<input type="file" name="file" id="file" />
<label class="file__btn" id="file_btn" for="file">Выберите файл</label>
<div class="file__info">
<div class="file__name" id="file_name"></div>
<div class="file__btn-close" id="file_btn_close"></div>
</div>
</div>
<div class="file__hint">
<span>Максимум 20 Мб;</span>
<span>В формате jpeg, jpg, png, gif, svg</span>
</div>
</div>
Здесь:
- file__btn — кнопка для выбора файла
- file__name — имя файла (после его загрузки)
- file__close — кнопка для удаления файла
- file__hint — требования к загружаемому файлу
Мы не будем использовать стандартный инпут (далее в стилях его уберем). Вместо этого создадим свою кнопку file__btn, которая будет ссылаться на инпут.
Стили
Комментарии приведены в коде.
/* Стилизуем бокс для загрузки файла */
.file-box {
display: flex;
flex-direction: column;
width: 100%;
margin-bottom: 30px;
}
/* Стилизуем поле с кнопкой и названием файла */
.file__field {
display: flex;
align-items: center;
margin-bottom: 8px;
}
/* Убираем дефолтный инпут */
#file {
display: none;
}
/* Стилизуем кнопку загрузки файла */
.file__btn {
display: inline-block;
color: #fff;
font-size: 15px;
background-color: #3e2093;
outline: none;
border: none;
padding: 10px 20px;
border-radius: 7px;
transition: 0.2s;
cursor: pointer;
}
.file__btn:hover {
background-color: #4517c2;
}
/* Стилизуем поле с названием файла и кнопкой закрыть */
.file__info {
display: flex;
align-items: center;
padding: 0 10px;
margin-left: 10px;
}
.file__name {
margin-bottom: 4px;
color: #888;
font-size: 14px;
word-spacing: 1px;
user-select: none;
}
.file__btn-close {
background: none;
outline: none;
border: none;
font-size: 20px;
color: red;
margin-left: 5px;
cursor: pointer;
padding: 3px;
font-weight: bold;
}
/* Стилизуем поле с подсказками */
.file__hint {
color: #516d7b;
font-size: 14px;
}
Скрипт
Комментарии даны в коде.
// Считываем нужные элементы
const file = document.querySelector("#file");
const fileName = document.querySelector("#file_name");
const fileBtnClose = document.querySelector("#file_btn_close");
// Задаем максимальный размер файла 20 Мб
const maxSize = 20 * 1024 * 1024;
// При загрузки файла - вызываем функцию проверки файла
file.addEventListener("change", (e) => {
checkFile(file.files[0]);
});
// Обработчик кнопки удаления файла
fileBtnClose.addEventListener("click", (e) => {
e.preventDefault();
fileReset();
});
// Функция проверки файла
function checkFile(file) {
// проверяем тип файла
if (
![
"image/jpeg",
"image/jpg",
"image/png",
"image/gif",
"image/svg+xml",
].includes(file.type)
) {
alert("Разрешены только указанные форматы");
fileReset();
return;
}
// проверяем размер файла (<20 Мб)
if (file.size > maxSize) {
alert("Файл должен быть менее 20 Мб");
fileReset();
return;
}
showFileName(file);
}
// Сброс полей поля файла
function fileReset() {
file.value = ""; // удаляем сам файл
fileName.textContent = ""; // удаляем имя файла
fileBtnClose.textContent = ""; // убираем кнопку удаления
}
// Выводим имя файла и кнопку удаления
function showFileName(file) {
fileName.textContent = file.name;
fileBtnClose.textContent = "×";
}
Чтобы файл отправлялся, необходимо в существующую функцию formSubmit добавить код.
async function formSubmit() {
const data = serializeForm(form);
data.append("image", file.files[0]); // добавить
// остальной код ..
}
Добавляем файл к письму
В скрипте send_mail.php необходимо добавить PHP-код, для того, чтобы приложить файл к письму.
// .. остальной код
if (!empty($_FILES["image"]["tmp_name"])) {
// путь загрузки файла
$filePath = __DIR__ . "/" . $_FILES["image"]["name"];
// грузим файл
if (copy($_FILES["image"]["tmp_name"], $filePath)) {
$fileAttach = $filePath;
$mail->addAttachment($fileAttach);
}
}
// .. остальной код
Исходник из урока
Скачать исходный код из данного урока вы можете по ссылке из моего GitHub.
Здравствуйте, подскажите как поменять путь для хранения файла, или его автоматического удаления. Грузит файлы в корневую папку.
А где прописывать e-mail на который будут отправляться данные с заявки?
Нашёл) не публикуйте
Вы умничка, я искал такую форму с телефоном и добавлением файла, работает все замечательно, немного сделал под себя, кто хочет может посмотреть демо https://aneg1965.brest.by/3/index.html целую вашу светлую голову, дай вам бог здоровья…