Объедините функцию google.script.run и javascript

Я создаю пользовательскую форму «Google Forms» с функцией загрузки файлов. Форма использует пользовательскую страницу «Спасибо» (см. 1-ю строку: iframe).
Я нашел сценарий загрузки файлов, который нужно запустить в среде Google Script, и он будет загружать файлы на мой Google Диск.

Теперь мне нужно объединить этот скрипт загрузки с моей пользовательской формой Google. Но я точно не знаю, как этого добиться, потому что есть действия, которые необходимо объединить, и загрузка файла должна быть завершена, прежде чем переходить на страницу «Спасибо».

Я попытался объединить его, который выглядит как код ниже.

Форма:

<iframe name = "hidden_iframe" id = "hidden_iframe" style = "display:none;" onload = "if (submitted)  { picUploadJs(myForm); }"></iframe>

<form id = "myForm" action = "https://docs.google.com/forms/d/e/xxx/formResponse" target = "hidden_iframe" onsubmit = "submitted=true;">
     <input placeholder = "1234" name = "entry.1234" id = "user" type = "text">
     <label for = "user">User:</label>

     <input name = "picToLoad" type = "file" />

     <div id = "status" style = "display: none">
       Uploading. Please wait...
     </div

   <button type = "submit" name = "action">Send</button>
</form>

Скрипт загрузки:

<script>

  function picUploadJs(frmData) {

    document.getElementById('status').style.display = 'inline';

    google.script.run
      .withSuccessHandler(updateOutput)
      .processForm(frmData)
    };

  function updateOutput() {

    var outputDiv = document.getElementById('status');
    outputDiv.innerHTML = "The File was UPLOADED!";
    window.location='https://thankyoupage/';
  }

</script>

Теперь это приводит к: Данные для ввода в форму отправляются, появляется текст статуса загрузки, но ничего не происходит: "Идет загрузка. Пожалуйста, подождите...".

Результат должен быть: Отправка входных данных формы, загрузка файла на диск и перенаправление на страницу благодарности.

Обновлено: Код Google-скрипта

function doGet(e) {
  return HtmlService.createTemplateFromFile('test')
    .evaluate() // evaluate MUST come before setting the Sandbox mode
    .setTitle('Name To Appear in Browser Tab')
    //.setSandboxMode();//Defaults to IFRAME which is now the only mode available
}

function processForm(theForm) {
  var fileBlob = theForm.picToLoad;

  Logger.log("fileBlob Name: " + fileBlob.getName())
  Logger.log("fileBlob type: " + fileBlob.getContentType())
  Logger.log('fileBlob: ' + fileBlob);

  var fldrSssn = DriveApp.getFolderById('xxxx');
    fldrSssn.createFile(fileBlob);

  return true;
}

Могу я спросить вас о processForm() скрипта Google Apps?

Tanaike 09.04.2019 01:46

Я добавил код скрипта Google в свой исходный пост.

Bldjef 09.04.2019 09:03

Спасибо за ответ. Прежде чем изменить ваш сценарий, я хотел бы подтвердить вашу текущую ситуацию. В вашей текущей ситуации, когда нажимается кнопка «Отправить», отправляется форма Google, запускается picUploadJs() и файл создается на Google Диске? Пожалуйста, расскажите мне о вашей текущей ситуации, когда нажата кнопка "Отправить".

Tanaike 09.04.2019 10:46

Когда нажимается «Отправить»: форма Google отправляется, picUploadJs() запускается, но только частично: стиль элемента «статус» меняется на inline, но функция загрузки google.script.run, похоже, не запускается или работает неправильно.

Bldjef 09.04.2019 11:36

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

Tanaike 09.04.2019 14:02
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
5
223
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  • Когда вы нажимаете кнопку «Отправить»,
    • Гугл форма работает нормально.
    • document.getElementById('status').style.display = 'inline' работает.
    • Функция processForm(frmData) в Google Apps Script не работает.
    • Функция updateOutput() в Javascript не работает.

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

Точки модификации:

  • В этой модификации файл получен по событию onclick, при этом скрипт отправки в Google Form не изменен.
  • Полученный файл конвертируется в base64 и отправляется в Google Apps Script.

Модифицированный скрипт:

HTML:

<form id = "myForm" action = "https://docs.google.com/forms/d/e/xxx/formResponse" target = "hidden_iframe" onsubmit = "submitted=true;">
  <input placeholder = "1234" name = "entry.1234" id = "user" type = "text">
  <label for = "user">User:</label>
  <input name = "picToLoad" type = "file" id = "sampleFile" /> <!-- Modified -->
  <div id = "status" style = "display: none">
  Uploading. Please wait...
  </div>
  <button type = "submit" name = "action" id = "sampleId" >Send</button> <!-- Modified -->
</form>

Javascript:

<script>
  // Below script was added.
  document.getElementById("sampleId").onclick = function(e) {
    e.stopPropagation();
    e.preventDefault();
    var file = document.getElementById("sampleFile").files[0];
    const f = new FileReader();
    f.onload = (e) => {
      const data = e.target.result.split(",");
      const obj = {fileName: file.name, mimeType: data[0].match(/:(\w.+);/)[1], data: data[1]};
      picUploadJs(obj);
    }
    f.readAsDataURL(file);
  };

  function picUploadJs(frmData) {
    document.getElementById('status').style.display = 'inline';
    google.script.run.withSuccessHandler(updateOutput).processForm(frmData)
  };

  function updateOutput() {
    var outputDiv = document.getElementById('status');
    outputDiv.innerHTML = "The File was UPLOADED!";
    window.location='https://thankyoupage/';
  }
</script>

Скрипт Google Apps:

function processForm(theForm) {
  var fileBlob = Utilities.newBlob(Utilities.base64Decode(theForm.data), theForm.mimeType, theForm.fileName);
  var fldrSssn = DriveApp.getFolderById('xxxx');
  fldrSssn.createFile(fileBlob);
  return true;
}

Примечание:

  • Когда файл выбран и нажата кнопка «Отправить», файл отправляется в Google Apps Script и создается как файл на Google Диске во время отправки формы Google. Затем запускается updateOutput() на стороне Javascript.
  • В этом модифицированном скрипте используется блоб. Таким образом, максимальный размер файла для загрузки составляет 50 МБ. Пожалуйста, будьте осторожны с этим.

Редактировать 1:

По вашему комментарию выяснилось, что When I remove the id=sampleId from the submit button, the Google Form data is submitted correctly. Используя это, проверьте следующую модификацию.

В этой модификации убрали id = "sampleId" и событие запускается по имени элемента.

HTML:

<form id = "myForm" target = "hidden_iframe" onsubmit = "submitted=true;">
  <input placeholder = "1234" name = "entry.1234" id = "user" type = "text">
  <label for = "user">User:</label>
  <input name = "picToLoad" type = "file" id = "sampleFile" />
  <div id = "status" style = "display: none">
  Uploading. Please wait...
  </div>
  <button type = "submit" name = "action">Send</button> <!-- Modified -->
</form>

Javascript:

var button = document.getElementsByName('action')[0]; // Modified
button.onclick = function(e) { // Modified
  e.stopPropagation();
  e.preventDefault();
  var file = document.getElementById("sampleFile").files[0];
  const f = new FileReader();
  f.onload = (e) => {
    const data = e.target.result.split(",");
    const obj = {fileName: file.name, mimeType: data[0].match(/:(\w.+);/)[1], data: data[1]};
    picUploadJs(obj);
  }
  f.readAsDataURL(file);
};

Редактировать 2:

Я обновил HTML и Javascript. Пожалуйста, подтвердите. Сценарий Google Apps не изменен.

HTML:

<iframe name = "hidden_iframe" id = "hidden_iframe" style = "display:none;" onload = "if (submitted)  { picUploadJs(myForm); }"></iframe>
<form id = "myForm" action = "https://docs.google.com/forms/d/e/xxx/formResponse" target = "hidden_iframe" onsubmit = "submitted=true;">
  <input placeholder = "1234" name = "entry.1234" id = "user" type = "text">
  <label for = "user">User:</label>
  <input name = "picToLoad" type = "file" id = "sampleFile" /> <!-- Modified -->
  <div id = "status" style = "display: none">
  Uploading. Please wait...
  </div>
  <button type = "submit" name = "action">Send</button>
</form>

Javascript:

<script>
  // This function was modified.
  function picUploadJs(myForm) {
    var file = document.getElementById("sampleFile").files[0];
    const f = new FileReader();
    f.onload = (e) => {
      const data = e.target.result.split(",");
      const obj = {fileName: file.name, mimeType: data[0].match(/:(\w.+);/)[1], data: data[1]};
      document.getElementById('status').style.display = 'inline';
      google.script.run.withSuccessHandler(updateOutput).processForm(obj);
    }
    f.readAsDataURL(file);
  }

  function updateOutput() {
    var outputDiv = document.getElementById('status');
    outputDiv.innerHTML = "The File was UPLOADED!";
    window.location='https://thankyoupage/';
  }
</script>

Спасибо, что нашли время, чтобы понять все это для меня! Я изменил свой сценарий с учетом ваших изменений, но, к сожалению, теперь он не отправляет данные формы Google. Однако он загружает файл на Google Диск и перенаправляет на страницу благодарности. Когда я удаляю id=sampleId из кнопки отправки, данные формы Google отправляются правильно (но, конечно, функция загрузки больше не работает).

Bldjef 09.04.2019 15:20

Может быть, вы забыли код iframe? Потому что эта строка также использовалась в моем исходном коде: <iframe name = "hidden_iframe" id = "hidden_iframe" style = "display:none;" onload = "if (submitted) { picUploadJs(myForm); }"></iframe> В настоящее время я пытаюсь заставить это работать так, но пока не удалось. <iframe name = "hidden_iframe" id = "hidden_iframe" style = "display:none;" onload = "if (submitted) { upload(); }"></iframe> И поместите свой скрипт в функцию: function upload() { //your script };

Bldjef 09.04.2019 16:23

Хорошо, я добавил эту строку после тега </head>, потому что ее не было и поэтому if (submitted) не работал: <script type = "text/javascript">var submitted=false;</script>. Но, к сожалению, файл не загружается.

Bldjef 09.04.2019 16:36

@Bldjef Спасибо за ответ. Я прошу прощения за неудобства. Из вашего ответа я изменил сценарий. Не могли бы вы подтвердить это? Если это еще не сработало, прошу прощения. Кстати, в модификации я использовал событие onclick вместо <iframe>...</iframe>.

Tanaike 10.04.2019 00:10

Извините, но он по-прежнему не отправляет данные формы. Я думаю, что скрипт загрузки файла получает «более высокий приоритет» (или быстрее?) и пропускает функцию действия из тега <form>.

Bldjef 10.04.2019 10:13

@Bldjef Спасибо за ответ и тестирование. Я прошу прощения за неудобства. Поэтому я хотел бы подтвердить ситуацию и изменить ее. Если вы можете дать мне время, чтобы сделать, я рад.

Tanaike 10.04.2019 10:51

@Bldjef Прошу прощения за неудобства. Я обновил свой ответ. Не могли бы вы подтвердить это? В этой модификации снова использовалось <iframe>...</iframe>. Таким образом, я могу подтвердить, что оба представления могут быть выполнены. Если это не сработало, прошу прощения.

Tanaike 10.04.2019 14:23

Спасибо, это работает! Ты восхитителен! Как вы думаете, можно ли выбрать несколько файлов и загрузить их? Я добавляю multiple в поле <input>, но я думаю, что нам также нужно прочитать весь массив, верно?

Bldjef 10.04.2019 14:39

Уже понял, нашел ваш пример на Gist Github! :) У меня есть еще несколько вопросов, может быть, я могу отправить вам электронное письмо или перейти в чат?

Bldjef 10.04.2019 16:44

Давайте продолжить обсуждение в чате.

Bldjef 10.04.2019 16:44

@Bldjef Спасибо за ответ. Я рад, что ваша проблема была решена. О вашем новом вопросе. Я не могу понять вашу ситуацию. Я хотел бы понять ваш новый вопрос. Итак, вы можете опубликовать это как новый вопрос? В это время, пожалуйста, включите подробную информацию о вашей ситуации. Это поможет пользователям, включая меня, подумать о вашем решении. Если вы можете сотрудничать, чтобы решить вашу проблему, я рад.

Tanaike 11.04.2019 00:27

Спасибо, Танайке, создан новый вопрос: stackoverflow.com/questions/55626979/…

Bldjef 11.04.2019 09:32

@Bldjef Спасибо за ваш ответ. Я предложил модифицированный сценарий. Не могли бы вы подтвердить это? Кстати, вы ссылались на этот скрипт?

Tanaike 11.04.2019 10:40

Другие вопросы по теме