/ Адаптивность / Ajax форма с вложением файла

Ajax форма с вложением файла

HIT

Долго искал и нашел (здесь www.thenerdyblog.com) отличное решение — форма с вложением файла на ajax.

Форма

<form id="contact-form" method="post" enctype="multipart/form-data">
	<div class="form-group">
		<label for="fname">First Name:</label>
		<input type="text" class="form-control" id="fname">
	</div>
	<div class="form-group">
		<label for="email">Email Address:</label>
		<input type="email" class="form-control" id="email_address">
	</div>
	<div class="form-group">
		<label for="attachment">File attachment:</label>
		<input type="file" name="file_attach" class="input-field"/>
	</div>

	<button type="button" id="submit" class="btn btn-default btn-dark">Submit</button>
</form>	

<div id="response"></div>
Важно чтобы кнопка отправки формы была именно button, а не полем input (type=»submit»). Иначе работать не будет.

Скрипт

$(document).ready(function() {

	$("#submit").click(function(e) {

		var proceed = true;

		if(proceed) { //everything looks good! proceed...

			//data to be sent to server        
			var m_data = new FormData();   
			m_data.append( 'first_name', $('#fname').val());
			m_data.append( 'email_address', $('#email_address').val());
			m_data.append( 'file_attach', $('input[name=file_attach]')[0].files[0]);

			//instead of $.post() we are using $.ajax()
			//that's because $.ajax() has more options and flexibly.

			$.ajax({
				url: '/wp-content/themes/meisterwerk-2/process.php',
				data: m_data,
				processData: false,
				contentType: false,
				type: 'POST',
				dataType:'json',
				success: function(response){
					//load json data from server and output message    
					if(response.type == 'error') { //load json data from server and output message    
						output = '<div class="error">'+response.text+'</div>';
					} else {
						output = '<div class="success">'+response.text+'</div>';
					}
					$("#response").hide().html(output).slideDown();
				}
			});

		}

	});
});

Файл-обработчик

<?php    

//Recepient Email Address
$to_email       = "mail@mail.ru";

//check if its an ajax request, exit if not
if(!isset($_SERVER['HTTP_X_REQUESTED_WITH']) AND strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
	$output = json_encode(array( //create JSON data
		'type'=>'error',
		'text' => 'Sorry Request must be Ajax POST'
	));
	die($output); //exit script outputting json data
}

//Sanitize input data using PHP filter_var().
$first_name      = filter_var($_POST["first_name"], FILTER_SANITIZE_STRING);
$email_address   = filter_var($_POST["email_address"], FILTER_SANITIZE_EMAIL);
$subject         = "Your Email Subject Goes Here...";

 
//Textbox Validation 
if(strlen($first_name)<4){ // If length is less than 4 it will output JSON error.
	$output = json_encode(array('type'=>'error', 'text' => 'Name is too short or empty!'));
	die($output);
}



$message = '<html><body>';
$message .= "<p><strong>First Name:</strong> " . strip_tags($_POST['first_name']) . "</p>";
$message .= "<p><strong>Email Address :</strong> " . strip_tags($_POST['email_address']) . "</p>";
$message .= "</body></html>";


$file_attached = false;
if(isset($_FILES['file_attach'])) { //check uploaded file

	//get file details we need
	$file_tmp_name    = $_FILES['file_attach']['tmp_name'];
	$file_name        = $_FILES['file_attach']['name'];
	$file_size        = $_FILES['file_attach']['size'];
	$file_type        = $_FILES['file_attach']['type'];
	$file_error       = $_FILES['file_attach']['error'];



	//exit script and output error if we encounter any
	if($file_error>0) {
		$mymsg = array(
		1=>"The uploaded file exceeds the upload_max_filesize directive in php.ini",
		2=>"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form",
		3=>"The uploaded file was only partially uploaded",
		4=>"No file was uploaded",
		6=>"Missing a temporary folder" );
		 
		$output = json_encode(array('type'=>'error', 'text' => $mymsg[$file_error]));
		die($output);
	}
	 
	//read from the uploaded file & base64_encode content for the mail
	$handle = fopen($file_tmp_name, "r");
	$content = fread($handle, $file_size);
	fclose($handle);
	$encoded_content = chunk_split(base64_encode($content));
	
	//now we know we have the file for attachment, set $file_attached to true
	$file_attached = true;

}

if($file_attached) { //continue if we have the file
   
	// a random hash will be necessary to send mixed content
	$separator = md5(time());
 
	// carriage return type (RFC)
	$eol = "\r\n";
 
	// main header (multipart mandatory)
	$headers = "From:Fromname <info@fromemail.com>" . $eol;
	$headers .= "MIME-Version: 1.0" . $eol;
	$headers .= "Content-Type: multipart/mixed; boundary=\"" . $separator . "\"" . $eol;
	$headers .= "Content-Transfer-Encoding: 7bit" . $eol;
	$headers .= "This is a MIME encoded message." . $eol;
	
	// message
	$body .= "--" . $separator . $eol;
	$body .= "Content-type:text/html; charset=utf-8\n";
	$body .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
	$body .= $message . $eol;
 
	// attachment
	$body .= "--" . $separator . $eol;
	$body  .= "Content-Type:".$file_type." ";
	$body .= "Content-Type: application/octet-stream; name=\"" . $file_name . "\"" . $eol;
	$body .= "Content-Transfer-Encoding: base64" . $eol;
	$body .= "Content-Disposition: attachment; filename=\"".$file_name."\"".$eol.$eol; // !Обязательно два $eol иначе приходит изображение с 0 Kb
	$body .= $encoded_content . $eol;
	$body .= "--" . $separator . "--";
	
} else {
	
	$eol = "\r\n";
	
	$headers = "From: Fromname <info@fromemail.com>" . $eol;
	$headers .= "Reply-To: ". strip_tags($email_address) . "\r\n";
	$headers .= "MIME-Version: 1.0\r\n";
	$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
	$body .= $message . $eol;

}

$send_mail = false; // в одном проекте без этого была ошибка
$send_mail = mail($to_email, $subject, $body, $headers);

if(!$send_mail) {
	//If mail couldn't be sent output error. Check your PHP email configuration (if it ever happens)
	$output = json_encode(array('type'=>'error', 'text' => 'Could not send mail! Please check your PHP mail configuration.'));
	die($output);
}else{
	$output = json_encode(array('type'=>'message', 'text' => 'Hi '.$first_name .' Thank you for your order, will get back to you shortly'));
	die($output);
}

Если нужно чтобы вложение было обязательным, то в условии else прописываем ошибку:

} else {
	
	$output = json_encode(array('type'=>'error', 'text' => 'Вложите файл с рецептом'));
	die($output);

}

Проверки

Проверки полей email и телефон

if(strlen($email_address)<1){
	$output = json_encode(array('type'=>'error', 'text' => 'Ведите свой E-mail'));
	die($output);
} elseif (!filter_var($email_address, FILTER_VALIDATE_EMAIL)) {
	$output = json_encode(array('type'=>'error', 'text' => 'E-mail указан не корректно'));
	die($output);
}

if(strlen($phone_number)<1){
	$output = json_encode(array('type'=>'error', 'text' => 'Ведите свой телефон'));
	die($output);
} elseif(!preg_match('/^[0-9]{11}+$/', $phone_number)) {
	$output = json_encode(array('type'=>'error', 'text' => 'Телефон указан не корректно (нужно указать только 11 цифр, без + и -)'));
	die($output);
}

Проверка поля «принятие» (например согласие с обработкой персональных данных).

Необходимо в скрипте добавить перехват и передачу значения (у поля должен быть id acceptance):

if ( $('#acceptance').is(':checked') ) {
	m_data.append( 'acceptance', '1');
}

Проверка в файле-обработчике:

if( !isset($acceptance) ){
	$output = json_encode(array('type'=>'error', 'text' => 'Вы должны согласится на обработку персональных данных'));
	die($output);
}

Стилизовать кнопку вложения

Верстка

<div>
	<input class="form-field form-file inputfile" type="file" name="file_attach" id="file" data-multiple-caption="{count} files selected" multiple>
	<label id="form-file-btn" for="file"><img src="/wp-content/themes/bastion/img/clip.svg"><span>Прикрепите резюме</span></label>
</div>

Стили

#form-file-btn {
    background: #eee;
    width: 100%;
    display: flex;
    text-align: center;
    border-radius: 10px;
    padding: 15px 23px;
    font-weight: 300;
    cursor: pointer;
    justify-content: center;
}

#form-file-btn img {margin-right: 7px;}

Код svg-изображения скрепки

<svg width="19" height="18" viewBox="0 0 19 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.7335 1.70988L17.2717 1.25426C16.4521 0.445401 15.3606 0 14.1984 0C13.0292 0 11.9294 0.449888 11.1028 1.2655L0.915275 11.2092C-0.301829 12.4101 -0.305571 14.3606 0.906971 15.5572L1.22625 15.8723C1.83223 16.4702 2.68094 16.8132 3.55461 16.8132C4.39128 16.8132 5.1642 16.5051 5.73106 15.9459L14.8773 6.92073C15.5896 6.21779 15.5915 5.0762 14.8817 4.37587L14.7112 4.20755C14.3665 3.86738 13.9072 3.68008 13.4182 3.68014C12.9267 3.68014 12.4645 3.86914 12.1169 4.2122L3.66297 12.5542C3.52707 12.6883 3.52883 12.904 3.66689 13.036C3.80501 13.168 4.02704 13.1662 4.16305 13.0322L12.617 4.69026C12.8317 4.47838 13.1163 4.36162 13.4182 4.36162C13.7178 4.36156 13.9993 4.47662 14.2111 4.68549L14.3815 4.85381C14.8242 5.29058 14.8223 6.00341 14.3772 6.44268L5.23098 15.4678C4.7971 15.8959 4.20176 16.1317 3.55467 16.1317C2.86776 16.1317 2.20138 15.8629 1.72639 15.3942L1.40711 15.0792C0.461682 14.1462 0.465425 12.6246 1.41401 11.6886L11.6016 1.74486C12.2965 1.05907 13.2187 0.681419 14.1983 0.681419C15.171 0.681419 16.0849 1.05458 16.7716 1.73226L17.2334 2.18794C18.6598 3.59541 18.6542 5.89113 17.221 7.30531L6.97033 17.4202C6.83443 17.5544 6.83619 17.7701 6.97425 17.9021C7.0426 17.9674 7.13149 18 7.22037 18C7.31106 18 7.40176 17.966 7.47041 17.8983L17.7211 7.78337C19.4215 6.10552 19.427 3.38103 17.7335 1.70988Z" fill="black"/>
</svg>

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

( function ( document, window, index ) {
	var inputs = document.querySelectorAll( '.inputfile' );
	Array.prototype.forEach.call( inputs, function( input )
	{
		var label	 = input.nextElementSibling,
			labelVal = label.innerHTML;

		input.addEventListener( 'change', function( e )
		{
			var fileName = '';
			if( this.files && this.files.length > 1 )
				fileName = ( this.getAttribute( 'data-multiple-caption' ) || '' ).replace( '{count}', this.files.length );
			else
				fileName = e.target.value.split( '\\' ).pop();

			if( fileName )
				label.querySelector( 'span' ).innerHTML = fileName;
			else
				label.innerHTML = labelVal;
		});

		// Firefox bug fix
		input.addEventListener( 'focus', function(){ input.classList.add( 'has-focus' ); });
		input.addEventListener( 'blur', function(){ input.classList.remove( 'has-focus' ); });
	});
}( document, window, 0 ));
Важно чтобы идентификатор (например inputfile) был одним словом без дефисов. Видимо какая то особенность js.

PHP-проверка мобильного телефона

//Tel Validation
if(strlen($tel)<11){
	$output = json_encode(array('type'=>'error', 'text' => 'Введите свой телефон, в формате +79098087766, либо 89098087766'));
	die($output);
}

if( preg_match("/[^0-9+\(\)-]/", $tel) ) {
    $output = json_encode(array('type'=>'error', 'text' => 'Введите корректный телефон'));
	die($output);
}

Поделиться в соц. сетях:

  • Похожие записи
  • Комментарии
  • Вложения
Технология Ajax

Технология Ajax

AJAX — это технология, позволяющая обмениваться данными между браузером и сервером без перезагрузок страницы, что бывает весьма удобно, иногда необходимо. Простой запрос и обновление контента Создаем файл time.php с содержимым Читать далее »

Подгрузка отдельных блоков на странице

Подгрузка отдельных блоков на странице

Прочитал в одной из статей — как подгружать методом ajax целые куски кода, в том числе и php. Сам метод действительно оказался прост. В данной статье опишем ситуации где этот Читать далее »

/
Фильтр Ajax

Фильтр Ajax

Очередная попытка сделать фильтр wordpress, в этот раз применяя технологию ajax. По сути программирование фильтра — это изобретение велосипеда, но есть 2 момента: во-первых в процессе я начинаю лучше понимать Читать далее »

/

Добавить комментарий

Пока нет комментариев. Будь первым!

Ajax форма с вложением файла Ajax форма с вложением файла
Кнопка с мессенджерами
Рекомендации для васКнопка с мессенджерамиOpttour.ru
Спасибо! Наш менеджер свяжется с Вами в течении 5 минут.