Форма обратной связи с автоматическим скачиванием файла

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

Статья, по просьбе одного из читателей, так что, если у вас есть какие-то вопросы, можете писать в раздел «ваши предложения» или мне в социальные сети. Периодически такие посты «по заказам» появляются на блоге. Кроме того, человек обещал отблагодарить финансово, так что, выгода и вам и мне.

Вернемся к форме. На самом деле нужно давно переписать почти все статьи о контактных формах, которые есть на сайте, так как мне реально стыдно за них. Я обязательно засяду и обновлю всё, как только появится больше времени.

Сейчас, набравшись опыта, кажется, что они настолько «корявы», что многие просто бегут с блога, видя код представленный в тех статья. Спасибо всем, кто остался, буду исправляться и обновлять контент, делая его более актуальным.

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

Контактная форма с автоматическим скачиванием

Итак, давайте перейдем к форме. Исходник, как обычно, в конце статьи.

<form class="contact-form" id="price-form" method="POST">

 <div class="contact-form__title">
  <img class="contact-form__title-icon" src="./fileform/img/pdf.svg" alt="Прайс" width="50">
  <span>Прайс на разработку landing page</span>
 </div>

 <div class="contact-form__input-wrapper">
  <input name="name" class="contact-form__input contact-form__input_name" type="text" placeholder="Введите ваше имя">
  <div class="contact-form__msgs contact-form__msgs-name"></div>
 </div>

 <div class="contact-form__input-wrapper">
  <input name="tel" class="contact-form__input contact-form__input_tel" type="tel" placeholder="Введите ваш телефон">
  <div class="contact-form__msgs contact-form__msgs-tel"></div>
 </div>

 <input name="subject" class="contact-form__input contact-form__input_subject" type="hidden" name="subject" value="Скачали прайс">
 <button class="contact-form__button">Скачать прайс</button>

</form>

Для примера я сделал простую контактную форму с 2 полями и кнопкой. Кроме того, сделал одной скрытой поле в котором передаю тему, в данном случае уведомление о том, что скачали прайс. Блоки с классом "contact-form__msgs" под каждым из полей отвечают за вывод сообщения о том, что имя или телефон небыли заполнены. На видео, вы могли видеть их, подсвеченные красным.

Думаю, тут проблем возникнуть не должно. Как и многие свои скрипты и наработки, я часто помещаю код в отдельные папки, чтобы вам было удобнее работать с ними. Так же поступил и в этот раз. Все файлы, отвечающие за внешний вид и обработку формы, лежат в папке "fileform", вы можете не делать этого или переименовать так, как вам больше нравится, но не забудьте поменять везде пути на свои.

Структура проекта

Форма с автоматическим скачиванием файла

Если вы давно читаете блог, то могли видеть подобную структуру в других формах. Самое интересное находится в папке "js" и "php". Как обычно, в последнее время, для отправки данных я использую PHPMailer, так как с ней удобно работать и она позволяет легко прикрепить файл, в случае необходимости, к письму, как вложение. Но прежде, чем говорить об этом всем, давайте подключим остальные необходимые файлы в наш индексный файл.

Прежде всего, убедитесь, что у вас подключена библиотека jQuery, так как обработчик использует ее, для отправки формы без перезагрузки страницы. После этого подключим сам js файл и, попутно, еще одну библиотеку для маски ввода номер телефона, так как предвижу вопросы, как ее подключить. Все это у меня выглядит так:

<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Маска -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.mask/1.14.15/jquery.mask.min.js"></script>
<!--Скрипт формы -->
<script src="/fileform/js/contact-form.js"></script>

Кроме того, давайте сразу инициализируем маску и привяжем к нужному полю. В моем случае это поле с классом "contact-form__input_tel".

<script>
  $(function () {
     $('.contact-form__input_tel').mask('+7(000)000-00-00')
  });
</script>

Можете вынести в отдельный файл, я же инициализировал маску в конце документа, перед закрывающим тегом "body".

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

Настройка отправки

Теперь давайте рассмотрим папку с php-файлами. В папке phpmailer лежат файлы библиотеки. Их мы править не будем, поэтому ее пропускаем. Больше нас интересует файл "config.php", ведь именно там прописываются почты, с которой и на которую будут приходить письма.

 const SENDER = 'sender@yandex.ru';
 const CATCHER = 'catcher@list.ru';
  • "SENDER" - отправитель;
  • "CATCHER" - получатель.

Обратите внимание, что обе почты должны быть реальными. Если есть проблемы с доставкой на Яндекс-почту, то почитайте эту статью.

Файл "contact-form.php" отвечает за валидацию и отправку данных формы на почту. Скрипт достаточно длинный, поэтому не буду приводить его в статье. Если не планируете добавлять поля, то можете не открывать на редактирование и этот файл, ведь то, ради чего затевалась эта статья, находится в файле "contact-form.js", а именно на 33 строке.

(function ($) {
    $(".contact-form").submit(function (event) {
        event.preventDefault();
        let form = $('#' + $(this).attr('id'))[0];
        let fd = new FormData(form);
        let inpName = $(this).find('.contact-form__input_name').val();
        let inpTel = $(this).find('.contact-form__input_tel').val();
        let inpNameMsgs = $(this).find('.contact-form__msgs-name');
        let inpTelMsgs = $(this).find('.contact-form__msgs-tel');
        if (inpName.length === 0 || inpTel.length === 0) {
            if (inpName.length === 0) {
                inpNameMsgs.text('Введите имя');
            }
            if (inpTel.length === 0) {
                inpTelMsgs.text('Введите телефон');
            }
        } else {
            $.ajax({
                url: "/fileform/php/contact-form.php",
                type: "POST",
                data: fd,
                processData: false,
                contentType: false,
                success: function success(res) {
                    if (res === 'notName') {
                        inpNameMsgs.text('Введите имя');
                    } else if (res === 'notTel') {
                        inpTelMsgs.text('Введите телефон');
                    } else if (res === 'successmsgs') {
                        inpNameMsgs.text('');
                        inpTelMsgs.text('');
                        setTimeout(() => {
                            window.location = '/fileform/file/file.zip';
                        }, 1000);
                    }
                },
            });
        }

    });
}(jQuery));

Если php-обработчик вернул нам сообщение 'successmsgs', свидетельствующее, что форма прошла все проверки и данные были отправлены на почту, то обращаемся (переходим) к по указанному пути, где лежит файл. Таким образом и достигается искомый результат автоматического скачивания файла.

Кстати, если у вас форма со страницей благодарности, то можете просто разместить не ней, перед закрывающим тегом body:

<script>
(function ($) {
 setTimeout(() => {
   window.location = '/fileform/file/file.zip';
 }, 1000);
}(jQuery));
</script>

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

Форма с автоматическим скачиванием файла

Размер: 2360 КБ

А как вы реализуете подобный функционал?

29 комментариев

  1. Михаил

    Заявки приходят как положено! Но при нажатии на кнопку скачать файл у меня выдает "Not Found
    The requested document was not found on this server."
    В чем может быть проблема. Изменил только «config.php».

  2. dimadv7

    Проблема в пути к файлу. Он указан неправильно, так как не найден или отсутствует сам файл? Нет ли ошибки в названии?

  3. Михаил

    ошибки быть не должно. Указан данный путь.
    window.location = '../file/file.pdf';

  4. Михаил

    Решил проверить и не менял вообще не чего. И выдает опять эту ошибку)))

    1. dimadv7

      Вы же на сервере тестируете? И, если, ничего не менять, то работать не будет, потому что в папке file лежит файл в формате pdf, а в настройках скрипта запрашивается file.zip

    2. Михаил

      dimadv7, Менял на '../file/file.pdf'; и да конечно на сервере тестирую. Вот тут))) - _http://test.pchelkaservis.kz

  5. dimadv7

    Михаил, вы раз за разом пишите неправильный путь. Судя по тому, как вы пишите его, ваш файл должен лежать в _sitename.kz/file/file.pdf, в исходнике, файл лежит в _sitename.kz/fileform/file/file.pdf исправьте ситуацию и все заработает.

    1. Михаил

      dimadv7, ага заработало. У вас в статье просто не указанно что нужно писать полный путь к файлу и я выходил из папки js и входил в папку file. Спасибо все заработало.

    2. dimadv7

      Михаил, да там не обязательно полный нужен, просто правильно указать. Если как вы указали, то файл в другом месте лежать должен. А так, отлично, что разобрались)

  6. Гузель

    Доброго времени суток.
    Спасибо за информацию, очень нужна именно такая форма(со скачиванием)
    К сожалению, долго пыталась установить и ничего не получилось.
    В консоли пишет ошибку
    POST __http://office8q.beget.tech/fileform/fileform/php/contact-form.php 500 (Internal Server Error) jquery.min.js:2
    т.е ошибка в jquery.min.js:2

    Буду очень благодарна, если поможете
    Буду безмерно благодарна

    1. dimadv7

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

      Кроме того, jquery должен быть 3 версии, php желателен 7 и выше.

    2. Гузель

      dimadv7,
      К сожалению и на платном ошибка
      POST __http://istracenter.ru/fileform/php/contact-form.php 500 (Internal Server Error)
      send @ jquery.min.js:2
      ajax @ jquery.min.js:2
      (anonymous) @ contact-form.js:18(строка $.ajax({)
      dispatch @ jquery.min.js:2
      y.handle @ jquery.min.js:2

      jquery подключается через http
      другие скрипты работают

    3. dimadv7

      Гузель, по пути, который вы указали, нет файла. То есть вот тут:

      http://istracenter.ru/fileform/php/
      

      Нет файла contact-form.php

      Значит ошиблись в путях. Перепроверьте все.

  7. Ксения

    Здравствуйте!
    Почему у меня переходит к файлу а не скачивает?

  8. Олег

    Здравствуйте. Подскажите, а можно авто загрузку файла сделать для плагина Contact form 7 ?

    1. Дмитрий Давыдов

      Олег, да, думаю, можно. Что-то вроде такого будет:

      <script>
          document.addEventListener( 'wpcf7mailsent', function( event ) {
              if(event.detail.contactFormId=="1917"){ // 1322 это id формы для отслеживания
       
                  window.location = '/fileform/file/file.zip';       
                  console.log('Форма 1917 - отправлена!'); 
              } 
          }, false );
      </script>
      
  9. Денис

    Добрый вечер, Дмитрий. Подскажите пожалуйста такой вопрос - "Нужно, чтоб при отправке формы был редирект на страницу благодарности и автоматически скачивался файл."

    Пробую вот такой код:

    (function ($) {
    $(".contact-form").submit(function (event) {
    event.preventDefault();
    let form = $('#' + $(this).attr('id'))[0];
    let fd = new FormData(form);
    let inpTel = $(this).find('.contact-form__input_tel').val();
    $.ajax({
    url: "/fileform/php/contact-form.php",
    type: "POST",
    data: fd,
    processData: false,
    contentType: false,
    success: function success(res) {
    if (res === 'successmsgs') {
    setTimeout(() => {
    window.location = "thanks.html";
    window.location = '/fileform/file/file.pdf';
    }, 1000);
    }
    },
    });
    });
    }(jQuery));

    Но не работает все вместе. Только редирект на thanks.html или открывается файл для скачивания.
    Пробовал на странице thanks.html вставлять код, с вашего примера

    (function ($) {
    setTimeout(() => {
    window.location = '/fileform/file/file.zip';
    }, 1000);
    }(jQuery));

    но не работает.

    Вообщем по отдельности все работает но вместе нет.

  10. Дмитрий Давыдов

    Денис, на странице благодарности jQuery подключен?

  11. Денис

    Нет не была подключена. После подключения логика заработала следующим образом - после отправки формы идет редирект на страницу "Спасибо", а затем редирект на скачивание файла. При этом указывает на ошибку в пути и файл скачать нельзя (хотя путь правильный).
    Но мне не нужны два редиректа, нужно оставаться на странице "Спасибо" и автомат. скачать файл.
    Я могу все это выгрузить на хостинг для наглядности. Если у Вас будет время взглянуть?

  12. Дмитрий Давыдов

    Денис, не нужно, пока. Путь, значит, точно не правильный. Пишите от корня сайта путь (полный). А по поводу второго редиректа, можно создать ссылку при помощи js и имитировать клик по ней. Тогда будет ожидаемый результат. Это на странице благодарности, вместо того, что было.

    let link = document.createElement('a');
    link.setAttribute('href','/fileform/file/file.zip');
    link.setAttribute('download','download');
    link.click();
    
  13. Денис

    Супер, все заработало как надо. Спасибо большое.

    1. Дмитрий Давыдов

      Отлично)

  14. Иван

    Благодарю! А подскажите, пожалуйста, как добавить новые поля? Например: Организация. Сообщение. Я не очень в этом разбираюсь.

  15. Азим

    Здравствуйте, Дмитрий. Скачал исходник и загрузил на хостинг, но почему-то файл после отправки данных открывается, но не скачивается. Через (расширение IDM для хрома) файл скачивается, но в любом случае идёт переход на файл. Как можно сделать, чтобы после скачивании не открывался файл?!

    1. Дмитрий Давыдов

      Азим, попробуйте так еще:

      /**
       * crossbrowser download
       * @param url
       * @param fileName
       */
      function cross_download(url, fileName) {
          var req = new XMLHttpRequest();
          req.open("GET", url, true);
          req.responseType = "blob";
          var __fileName = fileName;
          req.onload = function (event) {
              var blob = req.response;
              var contentType = req.getResponseHeader("content-type");
              if (window.navigator.msSaveOrOpenBlob) {
                  // Internet Explorer
                  window.navigator.msSaveOrOpenBlob(new Blob([blob], {type: contentType}), fileName);
              } else {
                  var link = document.createElement('a');
                  document.body.appendChild(link);
                  link.download = __fileName;
                  link.href = window.URL.createObjectURL(blob);
                  link.click();
                  document.body.removeChild(link); //remove the link when done
              }
          };
          req.send();
      }
      
      cross_download("/upload/file.jpg", "file.jpg");
      
  16. Азим

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

  17. Азим

    Но, почему-то при переходе на эту страницу сразу скачивается файл. Можно как-то запретить скачивание, когда форма не заполнена?

    1. Дмитрий Давыдов

      Вызывать функцию нужно после отправки формы.

      } else if (res === 'successmsgs') {
         inpNameMsgs.text('');
         inpTelMsgs.text('');
         setTimeout(() => {
            cross_download("/upload/file.jpg", "file.jpg");
         }, 1000);
      }
      
  18. Антон

    Форма отличная, но работает только на версии php 5.6, перевел сайт на версию php 8.0 и выше, форма перестала работать. Пожалуйста, подскажите, как запустить форму на новой версии php?

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