24.09.2015, 22:28
|
Кандидат Javascript-наук
|
|
Регистрация: 09.10.2013
Сообщений: 114
|
|
Подскажите, как сюда прикрутить ajax?
Здравствуйте. После двухнедельного искания формы с отправкой нескольких файлов на почту без перезагрузки, я её всё таки нашел. Но вот осталась одна проблема, как сюда добавить ajax? Посмотрите пожалуйста на код:
<form enctype="multipart/form-data" method="post" id="feedback-form">
<label for="nameFF">Имя:</label>
<input type="text" name="nameFF" id="nameFF" required placeholder="например, Иван Иванович Иванов" x-autocompletetype="name" class="w100 border">
<label for="contactFF">Email:</label>
<input type="email" name="contactFF" id="contactFF" required placeholder="например, ivan@yandex.ru" x-autocompletetype="email" class="w100 border">
<label for="fileFF">Прикрепить файл:</label>
<input type="file" name="fileFF[]" multiple id="fileFF" class="w100">
<label for="messageFF">Сообщение:</label>
<textarea name="messageFF" id="messageFF" required rows="5" placeholder="Детали заявки…" class="w100 border"></textarea>
<br>
<input value="Отправить" type="submit" id="submitFF">
</form>
document.getElementById('feedback-form').addEventListener('submit', function(evt){
var http = new XMLHttpRequest(), f = this;
evt.preventDefault();
http.open("POST", "contacts.php", true);
http.onreadystatechange = function() {
if (http.readyState == 4 && http.status == 200) {
alert(httfp.responseText);
if (http.responseText.indexOf(f.nameFF.value) == 0) { // очистить поле сообщения, если в ответе первым словом будет имя отправителя
f.messageFF.removeAttribute('value');
f.messageFF.value='';
}
}
}
http.onerror = function() {
alert('Извините, данные не были переданы');
}
http.send(new FormData(f));
}, false);
<?php
if (isset ($_POST['contactFF'])) {
$to = "@gmail.com"; // поменять на свой электронный адрес
$from = $_POST['contactFF'];
$subject = "Заполнена контактная форма с ".$_SERVER['HTTP_REFERER'];
$message = "Имя: ".$_POST['nameFF']."\nEmail: ".$from."\nIP: ".$_SERVER['REMOTE_ADDR']."\nСообщение: ".$_POST['messageFF'];
$boundary = md5(date('r', time()));
$filesize = '';
$headers = "MIME-Version: 1.0\r\n";
$headers .= "From: " . $from . "\r\n";
$headers .= "Reply-To: " . $from . "\r\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n";
$message="
Content-Type: multipart/mixed; boundary=\"$boundary\"
--$boundary
Content-Type: text/plain; charset=\"utf-8\"
Content-Transfer-Encoding: 7bit
$message";
for($i=0;$i<count($_FILES['fileFF']['name']);$i++) {
if(is_uploaded_file($_FILES['fileFF']['tmp_name'][$i])) {
$attachment = chunk_split(base64_encode(file_get_contents($_FILES['fileFF']['tmp_name'][$i])));
$filename = $_FILES['fileFF']['name'][$i];
$filetype = $_FILES['fileFF']['type'][$i];
$filesize += $_FILES['fileFF']['size'][$i];
$message.="
--$boundary
Content-Type: \"$filetype\"; name=\"$filename\"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=\"$filename\"
$attachment";
}
}
$message.="
--$boundary--";
if ($filesize < 10000000) { // проверка на общий размер всех файлов. Многие почтовые сервисы не принимают вложения больше 10 МБ
mail($to, $subject, $message, $headers);
echo $_POST['nameFF'].', Ваше сообщение получено, спасибо!';
} else {
echo 'Извините, письмо не отправлено. Размер всех файлов превышает 10 МБ.';
}
}
?>
Я знаю, что по средствам ajax можно сделать то что я хочу, но увы знаний у меня не хватает... В конце я хочу получить такой вид: человек нажимает на кнопку "отправить" и появляется анимация загрузки и потом выводится результат. либо положительный, либо отрицательный.
Пока что есть такой код.
$("#feedback-form").submit(function() {
var str = $(this).serialize();
$.ajax({
type: "POST",
url: "contacts.php",
data: str,
success: function(msg) {
if(msg == 'ok') {
$(".result").toggleClass("dis"); return false;
}
else {
$(".notresult").toggleClass("dis"); return false;
}
}
});
return false;
});
Но он, как вы понимаете, не получает msg == 'ok' . Письма уходят, но только почему то без файлов... Подскажите, как ему передать msg == 'ok' и не терять функцию отправки файлов?
P.S. Еще остаётся вопрос, как добавить анимацию загрузки? В какую строчку его засунуть ?
|
|
24.09.2015, 22:43
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
var http = new XMLHttpRequest().... это и есть Ajax, чего еще добавлять, кроме как обработку ответов сервера.
$subject = "Заполнена контактная форма с ".$_SERVER['HTTP_REFERER']; - так нельзя отправлять тему сообщения, ее нужно кодировать.
И принимать так файлы тоже нельзя - нужно уже на клиенте знать параметры сервера, которые накладывают ограничения на загрузку файлов.
|
|
24.09.2015, 23:51
|
Кандидат Javascript-наук
|
|
Регистрация: 09.10.2013
Сообщений: 114
|
|
1) ajax - это jquery, а текущий код работает без jquery. Тогда выходит, что var http = new XMLHttpRequest().... не ajax...
2)если было бы нельзя, то ничего бы не работало... Но всё работает.
Всё перестаёт работать, когда я пытаюсь прикрутить ajax)
|
|
25.09.2015, 01:04
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Сообщение от drkrol
|
ajax - это jquery
|
Это с каких пор Ajax стал принадлежать jQuery? Вы бы хотя бы читали, что это такое, а не пороли.... То что в jQuery есть методы работающие с Asynchronous Javascript and XML (Ajax - «асинхронный JavaScript и XML») еще не означает, что это ее детище. А XMLHttpRequest() это просто объект, который и служит для асинхронного обмена, и который используется и jQuery, нет у него своего объекта.
Сообщение от drkrol
|
если было бы нельзя, то ничего бы не работало... Но всё работает.
|
Вы в этом уверены? Кодировать надо тему сообщения и подстановки к адресу потому, что объявляемый вами charset не затрагивает их. И с большой долей вероятности вместо текста на каком либо почтовом сервисе или в почтовом клиенте вместо заголовка будет не понять что.
Вы так лихо file_get_contents($_FILES['fileFF']['tmp_name'][$i]), даже не проверяя загружено ли изображение.... и это по вашему работа? Работать с файлами нужно только после проверки ключа "error" на отсутствие ошибок.
Сервер накладывает ограничения на загрузку файлов - на макс. размер файла, на количество файлов и общий размер $_POST данных. Кроме этого любой уважающий себя хост всегда следит за 25 портом и отправлять почту любого размера не позволит.
Работает у вас так, на халяву, пока не гикнут вас с вашим подходом к написания скриптов, и получите вы по шапке. Тогда может задумаетесь как должно работать.
Последний раз редактировалось laimas, 25.09.2015 в 01:19.
|
|
25.09.2015, 13:19
|
Кандидат Javascript-наук
|
|
Регистрация: 09.10.2013
Сообщений: 114
|
|
Сообщение от laimas
|
Работает у вас так, на халяву, пока не гикнут вас с вашим подходом к написания скриптов, и получите вы по шапке. Тогда может задумаетесь как должно работать.
|
Не совсем понял вас... Как это гикнуть на мой подход? Если вы хорошо почитали мой пост, то вы поймёте, что скрипт написал не я, а взял его с сети.
Сообщение от laimas
|
Вы так лихо file_get_contents($_FILES['fileFF']['tmp_name'][$i]), даже не проверяя загружено ли изображение.... и это по вашему работа? Работать с файлами нужно только после проверки ключа "error" на отсутствие ошибок
|
Это уже другой вопрос. Сейчас стоит вопрос только о том как сделать анимацию загрузки и вывести результат через смену стиля (addclass)
Вы так отвечает будто там, в решении моего вопроса, много строк кода...
Прошу знающих людей помочь мне в этом простом для вас, и в сложном для меня деле.
|
|
25.09.2015, 15:16
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Сообщение от drkrol
|
Как это гикнуть на мой подход?
|
Да просто - загрузят вам файлов по размеру, за который вам хостер ваш может и по шапке дать. Вам ведь сказано было - так нельзя. А что от вас? Ну почти - "работает да и хрен с ним".
Первым делом, это нужно в панели управления узнать разрешения на почту, обычно это ограничения на количество сообщений отправляемых за единицу времени и на размер почтового отправлений. Из этого размера и нужно исходить, то есть еще на клиенте проверять размер загружаемых файлов, и по приему формы сервером опять проверять, и обязательно!
Сам сервер накладывает ограничения на загрузку файлов, которые тоже можно узнать в панели. Если панель не дает об этом полной информации, то это можно получить таким образом:
//макс. размер POST данных в МБ,
//этот размер должен превышать весь объем данных формы, включая и файлы
ini_get('post_max_size')+0;
//макс. размер загружаемого файла МБ
ini_get('upload_max_filesize')+0;
//количество загружаемых файлов, контролируется начиная с версии 5.2.12
ini_get('max_file_uploads');
Эти параметры также нужно передать на клиента, проверяя по ним загрузку файлов.
На сервере, тем более отправляя почту, нужно не "Это уже другой вопрос", а первостепенный вопрос, ибо вы не проверяя загружено или нет, плюхаете на почту, не проверяя ошибок, а нужно отправлять только в том случае, если их нет. Если они есть, то об этом должен знать клиент и причину ошибки. А для того чтобы не хвататься сразу за формирование сообщения, а проверить отсутствие ошибок загрузки, достаточно получить ключи массива $_FILES['error'] отличные от ноля:
if(!$e = array_diff($_FILES['fileFF']['error'], array(0))) {
if(!$size = array_sum(array_column($_FILES['fileFF'], 'size')) < $sizemail) {
//нет ошибок загрузки, формируем сообщение
//загружая файлы с проверкой is_uploaded_file
} //иначе сообщаем клиенту - низзя
} //иначе $e содержит массив ошибок, сообщаем клиенту
//функция array_column() доступна начиная с версии 5.5.0
//если версия ниже, функцию можно заменить пользовательской
function arrayColumn($a, $i) {
return array_values(array_diff(array_map(function($v) use($i) {
return $v[$i];
}, $a), array(null)));
}
//имена файлов всегда нужно обрабатывать как:
$filename = basename($_FILES['fileFF']['name']);
//пусть для письма как текст это и не страшно
//просто это должно стать привычкой
На клиенте эти параметры можно проверить получая соответствующие свойства массива files поля file. Как это делается и на этом форуме не раз приводилось, да и в сети об этом полно.
Тему почтового сообщения кодируют:
$subject ='=?utf-8?b?' . base64_encode('Заполнена контактная форма с '.$_SERVER['HTTP_REFERER']) . '?=';
//тоже самое делать и с данными для поля From, если к адресу добавляют текст
$headers = 'From: =?utf-8?B?' . base64_encode($data) . '?= <' .$email. '>' . PHP_EOL;
Последний раз редактировалось laimas, 25.09.2015 в 15:31.
|
|
25.09.2015, 16:18
|
Кандидат Javascript-наук
|
|
Регистрация: 09.10.2013
Сообщений: 114
|
|
1)Поменял
$filename = $_FILES['fileFF']['name'][$i];
на
$filename = basename($_FILES['fileFF']['name']);
и получил вот такое сообщение диалоговом окне:
<br /> <b> Warning</b>: basename () expects parameter 1 to be string array given in <b>F:\openserver\......\contacts.php</b> on line <b>26</b> <br /> mymail@123.ru. Ваше сообщение получено спасибо!
А на почту пришел файл noname... Открыть его нельзя.
$filename = basename($_FILES['fileFF']['name']); - только усложняет жизнь.
2)С этим строчками вообще не разобрался.
if(!$e = array_diff($_FILES['fileFF']['error'], array(0))) {
if(array_sum(array_column($_FILES['fileFF'], 'size')) < $sizemail) {
//нет ошибок загрузки, формируем сообщение
//загружая файлы с проверкой is_uploaded_file
} //иначе сообщаем клиенту - низзя
} //иначе $e содержит массив ошибок, сообщаем клиенту
//функция array_column() доступна начиная с версии 5.5.0
//если версия ниже, функцию можно заменить пользовательской
function arrayColumn($a, $i) {
return array_values(array_diff(array_map(function($v) use($i) {
return $v[$i];
}, $a), array(null)));
}
я так понимаю, я должен был получить, что то типа этого
if(!$e = array_diff($_FILES['fileFF']['error'], array(0))) {
if(array_sum(array_column($_FILES['fileFF'], 'size')) < $sizemail) {
for($i=0;$i<count($_FILES['fileFF']['name']);$i++) {
if(is_uploaded_file($_FILES['fileFF']['tmp_name'][$i])) {
$attachment = chunk_split(base64_encode(file_get_contents($_FILES['fileFF']['tmp_name'][$i])));
$filename = $_FILES['fileFF']['name'][$i];
$filetype = $_FILES['fileFF']['type'][$i];
$filesize += $_FILES['fileFF']['size'][$i];
$message.="
--$boundary
Content-Type: \"$filetype\"; name=\"$filename\"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=\"$filename\"
$attachment";
}
}
function arrayColumn($a, $i) {
return array_values(array_diff(array_map(function($v) use($i) {
return $v[$i];
}, $a), array(null)));
}
Но на выходе я получал: <br /> <b> Parse error</b>: syntax error, unexpected $end in <b>f:\openserver\...\contacts.php</b> on line <b>56</b> <br />
Кстати на 56 линии находится ?> и что за $end, я понятия не имею...
|
|
25.09.2015, 17:18
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Я же просто пишу пример, для единичного файла, а вы загружаете массив файлов, поэтому надо:
$filename = basename($_FILES['fileFF']['name'][$i]);
В сети ищите темы типа "как правильно загружать файлы" и подобное, там прочтете для чего это делается. Эта функция не усложняет, а помогает, просто не знаете вы языка, если копируете, а не понимаете.
Ошибка "syntax error, unexpected $end" гласит о том, что не закрыта конструкция, то есть, нет или лишняя фигурная скобка. Вы просто вырвали кусок кода из примера и вставили его себе, и конечно у вас нет закрывающих скобок, поэтому и ошибка. Должно быть так:
if(!$e = array_diff($_FILES['fileFF']['error'], array(0))) {
if(($size = array_sum(array_column($_FILES['fileFF'], 'size'))) < $sizemail) {
//формирование почтового отправления, то есть
//$to = "@gmail.com"; // поменять на свой электронный адрес
//$from = $_POST['contactFF'];
//и так далее
for($i=0;$i<count($_FILES['fileFF']['name']);$i++) {
if(is_uploaded_file($_FILES['fileFF']['tmp_name'][$i])) {
//добавление файлов к почте, то есть заполнение $attachment и т.д.
} else {
//подстава - файл левый, прекращаем работу скрипта
exit('Да и идите вы ...');
}
}
} else {
//формируем информацию о превышении размера файлов разрешенных для загруки
//то есть если их размер превышает размер $sizemail разрешенный для отправкой почтой
//$size - содержит размер всех загруженных файлов
}
} else {
//формируем информацию об ошибках загрузки файлов для пользователя
//ключи массива $e будут указывать на файлы загруженные с ошибками
}
А пользовательская функция arrayColumn() нужна только в том случае, если у вас версия РНР ниже 5.5.0 (ориентироваться надо не на локальный сервер, а реальный, тот что будет, устанавливая на локальном такую же версию, в Open Server это сделать легко), то есть так:
arrayColumn($_FILES['fileFF'], 'size')
вместо
array_column($_FILES['fileFF'], 'size')
при этом поместить ее не в этот скрипт отправки почты, а в подключаемый файл пользовательских функций, она не раз пригодится еще, о ее назначении тут.
Иначе эта функция не нужна, и нужно использовать стандартную array_column().
Последний раз редактировалось laimas, 25.09.2015 в 21:47.
|
|
25.09.2015, 19:39
|
Кандидат Javascript-наук
|
|
Регистрация: 09.10.2013
Сообщений: 114
|
|
Спасибо вам за помощь, но вы можете просто сказать, что нужно в ajax jquery изменить, чтобы он отправлял файлы?
$("#feedback-form").submit(function() {
var str = $(this).serialize();
$.ajax({
type: "POST",
url: "contacts.php",
data: str,
success: function(msg) {
if(msg == 'ok') {
$(".result").toggleClass("dis"); return false;
}
else {
$(".notresult").toggleClass("dis"); return false;
}
}
});
return false;
});
|
|
25.09.2015, 20:47
|
Профессор
|
|
Регистрация: 14.01.2015
Сообщений: 12,989
|
|
Я уже сказал - у вас есть в коде отправка именно Ajax методом - вот непосредственно строка отправки формы http.send(new FormData(f));, прикручивать сюда еще $.ajax jQuery совсем не нужно.
Только нужно добавить проверку на условия, не отправлять форму пока условия не будут соблюдены, а также возвращать ошибки при проверке формы на сервере. В общем нужно добавить диалог-клиент сервер. Ведь не только загрузку файлов проверять надо на сервере, но и заполнение полей необходимых, если они обязательные для заполнения.
|
|
|
|