(Обновлено 26.06.2018)
Данный скрипт идеально подойдет для форм при создании сайтов-визиток, каталогов, лендингов, где нужно отправить простую форму с прикрепленным файлом.
В скрипте используется проверка заполненности обязательных полей с помощью скрипта jquery.validation с последующей отправкой сообщения на e-mail администратора без перезагрузки страницы с помощью технологии ajax.
Демо-страницу можно посмотреть – тут.
Рассмотрим работу скрипта на примере:
Дана форма с полями: Имя, Телефон, Е-mail и "Описание заказа".
Код формы:
<form action="#" method="post" id="sendform" enctype="multipart/form-data">
<fieldset>
<h3>Форма заказа</h3>
<p>
<label>Имя*:</label>
<input name="name" value="" size="40" type="text" class="required" />
</p>
<p>
<label>Контактный номер*:</label>
<input name="tel" value="" size="40" class="required" type="tel" />
</p>
<p>
<label>E-mail:</label>
<input name="email" value="" size="40" type="email" />
</p>
<p>
<label>Описание заказа:</label>
<textarea name="message" cols="40" rows="10" /> </textarea>
</p>
<p>
<label>Прикрепить файл:</label>
<input name="file" value="1" size="40" type="file" />
</p>
<input value="Отправить" name="sendMail" type="submit" />
</fieldset>
</form>
! В форме, в которой происходит прикрепление файла, обязательно наличие аттрибута enctype=”multipart/form-data”.
Javascript код
Подключаем библиотеки jQuery и плагин валидации на страницу:
<script src="https://code.jquery.com/jquery-1.12.4.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js" type="text/javascript"></script>
Javascript код для валидации и ajax-отправки формы
// Как только страничка загрузилась
window.onload = function () {
// проверяем поддерживает ли браузер FormData
if(!window.FormData) {
alert("Браузер не поддерживает загрузку файлов на этом сайте");
}
}
$(document).ready(function(){
// =validation
var errorTxt = 'Ошибка отправки';
$("#sendform").validate({
submitHandler: function(form){
var form = document.forms.sendform,
formData = new FormData(form),
xhr = new XMLHttpRequest();
xhr.open("POST", "/send.php");
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if(xhr.status == 200) {
$("#sendform").html('<p class="thank">Данные отправлены!<p>');
}
}
};
xhr.send(formData);
}
});
})
Разберем более подробно этот код.
Для отправки файлов используется интерфейс FormData. Для кодирования данных метод FormData использует формат “multipart/form-data”. Это означает то, что он позволяет подготовить для отправки по AJAX как текстовые данные, так и файлы. При создании объекта FormData ему можно в качестве параметра указать DOM форму. В этом случае в объект FormData автоматически добавятся все поля (имяПоля:значение) этой формы.
О более детальной работе FormData можно почитать тут.
После загрузки страницы, с помощью строки if(!window.FormData)
проверяем доступность данного объекта. В случае, если он не доступен сообщаем об этом пользователю (для демонстрации в коде сообщение выводится алертом, на живом сайте так делать не надо – правильней будет в форме, скрывать поле для загрузки файлов). Это касается совсем старых браузеров. Для всех современных браузеров все будет работать.
При нажатии на кнопку “Отправить” проверяются обязательные поля на заполненность с помощью метода validate и в случае успешной проверки (submitHandler) создается новый объект FormData, происходит вызов скрипта send.php, который и производит отправку форму и прикрепленного к ней файла.
Затем вместо формы выводится сообщение об успешной отправке. За это отвечает строка
$("#sendform").html('<p class="thank">Данные отправлены!</p>');
PHP-скрипт отправки данных с формы
send.php
<?php
$to = 'info@proverstka.com.ua';
if ( isset( $_POST['sendMail'] ) ) {
$name = substr( $_POST['name'], 0, 64 );
$tel = substr( $_POST['tel'], 0, 64 );
$email = substr( $_POST['email'], 0, 64 );
$message = substr( $_POST['message'], 0, 250 );
if ( !empty( $_FILES['file']['tmp_name'] ) and $_FILES['file']['error'] == 0 ) {
$filepath = $_FILES['file']['tmp_name'];
$filename = $_FILES['file']['name'];
} else {
$filepath = '';
$filename = '';
}
$body = "Имя:\r\n".$name."\r\n\r\n";
$body .= "Контактный номер:\r\n".$tel."\r\n\r\n";
$body .= "E-mail:\r\n".$email."\r\n\r\n";
$body .= "Описание заказа:\r\n".$message;
send_mail($to, $body, $email, $filepath, $filename);
}
// Вспомогательная функция для отправки почтового сообщения с вложением
function send_mail($to, $body, $email, $filepath, $filename)
{
$subject = 'Тестирование формы с прикреплением файла с сайта proverstka.com.ua';
$boundary = "--".md5(uniqid(time())); // генерируем разделитель
$headers = "From: ".$email."\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .="Content-Type: multipart/mixed; boundary=\"".$boundary."\"\r\n";
$multipart = "--".$boundary."\r\n";
$multipart .= "Content-type: text/plain; charset=\"utf-8\"\r\n";
$multipart .= "Content-Transfer-Encoding: quoted-printable\r\n\r\n";
$body = $body."\r\n\r\n";
$multipart .= $body;
$file = '';
if ( !empty( $filepath ) ) {
$fp = fopen($filepath, "r");
if ( $fp ) {
$content = fread($fp, filesize($filepath));
fclose($fp);
$file .= "--".$boundary."\r\n";
$file .= "Content-Type: application/octet-stream\r\n";
$file .= "Content-Transfer-Encoding: base64\r\n";
$file .= "Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n";
$file .= chunk_split(base64_encode($content))."\r\n";
}
}
$multipart .= $file."--".$boundary."--\r\n";
mail($to, $subject, $multipart, $headers);
}
?>
Архив с примером
Демо-страница формы обратной связи с прикреплением файла
Дополнение от 28.12.2016
Отправка формы с прикреплением нескольких файлов
В элементе input, в котором прикрепляем файл, дописываем аттрибут multiple
(<input name=”file[]” value=”1″ size=”40″ type=”file” multiple />), что даст возможность выбора одновременно несколько файлов.
Изменяем php файл для обработки массива из нескольких файлов:
<?php
$to = 'info@proverstka.com.ua';
if ( isset( $_POST['sendMail'] ) ) {
$name = substr( $_POST['name'], 0, 64 );
$tel = substr( $_POST['tel'], 0, 64 );
$email = substr( $_POST['email'], 0, 64 );
$message = substr( $_POST['message'], 0, 250 );
if($_FILES)
{
$filepath = array();
$filename = array();
$i = 0;
foreach ($_FILES["file"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$filename[$i][0] = $_FILES["file"]["tmp_name"][$key];
$filename[$i][1] = $_FILES["file"]["name"][$key];
$i++;
}
}
}
$body = "Имя:\r\n".$name."\r\n\r\n";
$body .= "Контактный номер:\r\n".$tel."\r\n\r\n";
$body .= "E-mail:\r\n".$email."\r\n\r\n";
$body .= "Описание заказа:\r\n".$message;
send_mail($to, $body, $email, $filename);
}
// Вспомогательная функция для отправки почтового сообщения с вложением
function send_mail($to, $body, $email, $filename)
{
$subject = 'Тестирование формы с прикреплением файла с сайта proverstka.com.ua';
$boundary = "--".md5(uniqid(time())); // генерируем разделитель
$headers = "From: ".$email."\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .="Content-Type: multipart/mixed; boundary=\"".$boundary."\"\r\n";
$multipart = "--".$boundary."\r\n";
$multipart .= "Content-type: text/plain; charset=\"utf-8\"\r\n";
$multipart .= "Content-Transfer-Encoding: quoted-printable\r\n\r\n";
$body = $body."\r\n\r\n";
$multipart .= $body;
foreach ($filename as $key => $value) {
$fp = fopen($value[0], "r");
$content = fread($fp, filesize($value[0]));
fclose($fp);
$file .= "--".$boundary."\r\n";
$file .= "Content-Type: application/octet-stream\r\n";
$file .= "Content-Transfer-Encoding: base64\r\n";
$file .= "Content-Disposition: attachment; filename=\"".$value[1]."\"\r\n\r\n";
$file .= chunk_split(base64_encode($content))."\r\n";
}
$multipart .= $file."--".$boundary."--\r\n";
mail($to, $subject, $multipart, $headers);
}
?>
Демо-пример формы с прикреплением нескольких файлов на отдельной странице
Архив с примером
—-0e1da19ddc73ed414d8185b01e2d2035
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=”03_вечер-4×4.png”
iVBORw0KGgoAAAANSUhEUgAAB9AAAAUhCAIAAABcC4i7AACAAElEQVR42uzdh1JbWbOGYZGNbYKN
yaAM2OOoBNJWIKNE8Pzn/u/lgGGwEAo7rNDd65t6ixKMkINS1eOmV+y8vCe7CwNVordPoUsWeaS7
GtOB/Ko2a7reZ9SsIWQ2POnCdoUG5gXrEnmfL0JUUdKByc7tVtbVGeuOXnQauH2ynYTokFzHhtob
UElxDdYVX1Q3WtZMtaAV2FRVViZYeaN5Msr5Kf1cBeXS5df9UlMMzk5A2y3L+yWjWCK7G/IOYYe/
w9YRAsHD3y2xO/A9pLyTR3Za8l4Gu6ti930WyTD3E/PUrgfcjwWBuyl2zxpOsLnXDFO7JXOvygf3
9OsA7vrMPQZqp6TtRuX9EtRuwdkl4juEHf4OW0cICg98J8PukPdL9ex+QDCwO2VzP2NO7ZHY/dAR
dt8bXwnsbsvcsxaDuauhdkvgLtfc06ODuVcA7lScXbu2a5T3S1A7CWQXIe8Qdvg7eH14LSnBykHw
……………………. – вместо фото