无法正确提交自定义HTML表单数据到G表格和文件到G驱动器。

huangapple go评论70阅读模式
英文:

Note able to submit the custom html form data properly to the gsheet and file to gdrive

问题

这是HTML文件代码。

<form method="POST" action="'YOUR_GOOGLE_APPS_SCRIPT_URL'" class="bg-gray-100 p-6 rounded shadow" onsubmit="return validateForm()" id="upload-form">
    <div class="mb-4">
        <label for="email" class="text-primary font-semibold">邮箱 *</label>
        <input type="email" class="w-full border border-gray-300 rounded px-4 py-2 focus:outline-none focus:border-primary"
            id="email" name="email" required>
    </div>
    <div class="mb-4">
        <label for="name" class="text-primary font-semibold">姓名 *</label>
        <input type="text" class="w-full border border-gray-300 rounded px-4 py-2 focus:outline-none focus:border-primary"
            id="name" name="name" required>
    </div>
    <div class="mb-4">
        <label for="zip-file" class="text-primary font-semibold">请上传您的zip文件(仅支持.stl格式)</label>
        <input type="file" class="w-full border border-gray-300 rounded px-4 py-2 focus:outline-none focus:border-primary"
            id="zip-file" name="zip-file" accept=".zip" required>
    </div>
    <div class="mb-4">
        <label for="student-id" class="text-primary font-semibold">如果您是学生,请输入有效的身份证号以获得额外的学生折扣</label>
        <input type="file" class="w-full border border-gray-300 rounded px-4 py-2 focus:outline-none focus:border-primary"
            id="student-id" name="student-id">
    </div>
    <button type="submit" class="bg-primary text-white py-2 px-4 rounded-full hover:bg-blue-700"
        id="submit-button">提交</button>
</form>
<script>
    // 用你实际的Google Apps Script Web App URL替换'your_script_id_here'
    let url = "https://script.google.com/macros/s/your_script_id_here/exec";
    let form = document.getElementById("customer-form");
    let zipFileInput = document.getElementById("zip-file");
    let imageFileInput = document.getElementById("student-id");

    form.addEventListener('submit', (e) => {
        e.preventDefault(); // 阻止默认表单提交

        // 创建一个新的FormData对象
        let formData = new FormData(form);

        // 将文件上传添加到FormData
        handleFileUpload(zipFileInput, formData);
        handleFileUpload(imageFileInput, formData);

        // 使用fetch发送POST请求
        fetch(url, {
            method: "POST",
            body: formData
        })
        .then(response => response.text())
        .then(data => console.log(data))
        .catch(error => console.error(error));
    });

    function handleFileUpload(fileInput, formData) {
        let file = fileInput.files[0];
        if (!file) return;

        let fr = new FileReader();
        fr.addEventListener('loadend', () => {
            let res = fr.result;
            let spt = res.split("base64,")[1];

            let obj = {
                base64: spt,
                type: file.type,
                name: file.name
            };

            formData.append(fileInput.name, file);
            formData.append('file-info', JSON.stringify(obj));
        });

        fr.readAsDataURL(file);
    }
</script>

以下是我使用的Google Sheets App Script代码:

function doPost(e) {
    var jsonData = JSON.parse(e.postData.contents); // 从请求中解析JSON数据

    var spreadsheet = SpreadsheetApp.openById('1X57VuMPPN2mAIvbdbNCSCUdmfnQptor8E7i4tSmkjZ4');
    var subSheetName = 'Cx input'; // 替换为您的子表名称

    var subSheet = spreadsheet.getSheetByName(subSheetName);
    if (!subSheet) {
        subSheet = spreadsheet.insertSheet(subSheetName);
    }

    var rowData = [];

    rowData.push(jsonData.email);
    rowData.push(jsonData.name);

    // 上传.stl或.zip文件到Google Drive
    var folderId = '1iIxxTrYtwmlQPXn3qaAADFT-tUEVMZsT'; // 替换为您的Google Drive文件夹ID
    var fileBlob = Utilities.newBlob(jsonData['zip-file'], jsonData['zip-file'].type, jsonData['zip-file'].name); // 从JSON数据中获取文件内容并转换为Blob
    var folder = DriveApp.getFolderById(folderId); // 按ID获取文件夹
    var file = folder.createFile(fileBlob); // 在文件夹中创建文件
    var fileUrl = file.getUrl(); // 获取上传文件的URL
    rowData.push(fileUrl); // 在表格中存储文件URL

    // 上传图像文件到Google Drive
    var imageBlob = Utilities.newBlob(jsonData['student-id'], jsonData['student-id'].type, jsonData['student-id'].name); // 从JSON数据中获取图像内容并转换为Blob
    file = folder.createFile(imageBlob); // 在文件夹中创建文件
    fileUrl = file.getUrl(); // 获取上传图像的URL
    rowData.push(fileUrl); // 在表格中存储图像URL

    subSheet.appendRow(rowData);

    return ContentService.createTextOutput('表单成功提交');
}

您遇到的问题是CORS策略阻止了从脚本发出的请求。为了解决这个问题,您可以将以下代码添加到您的Google Apps Script的doPost函数中:

function doPost(e) {
    // ...

    // 设置CORS头部
    var headers = {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
        "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With",
        "Access-Control-Allow-Frontend-Headers": "X-Requested-With",
        "Access-Control-Max-Age": "86400"
    };

    return ContentService
        .createTextOutput('Form submitted successfully')
        .setMimeType(ContentService.MimeType.TEXT)
        .setHeaders(headers);
}

这应该解决CORS策略的问题。请确保将这段代码添加到您的doPost函数中,并重新部署您的Google Apps Script。

英文:

This is html file code.

        &lt;div class=&quot;mb-4&quot;&gt;
&lt;label for=&quot;email&quot; class=&quot;text-primary font-semibold&quot;&gt;Email *&lt;/label&gt;
&lt;input type=&quot;email&quot; class=&quot;w-full border border-gray-300 rounded px-4 py-2 focus:outline-none focus:border-primary&quot;
id=&quot;email&quot; name=&quot;email&quot; required&gt;
&lt;/div&gt;
&lt;div class=&quot;mb-4&quot;&gt;
&lt;label for=&quot;name&quot; class=&quot;text-primary font-semibold&quot;&gt;Name *&lt;/label&gt;
&lt;input type=&quot;text&quot; class=&quot;w-full border border-gray-300 rounded px-4 py-2 focus:outline-none focus:border-primary&quot;
id=&quot;name&quot; name=&quot;name&quot; required&gt;
&lt;/div&gt;
&lt;div class=&quot;mb-4&quot;&gt;
&lt;label for=&quot;zip-file&quot; class=&quot;text-primary font-semibold&quot;&gt;Please upload your zip file (.stl format only) which you
want to print.&lt;/label&gt;
&lt;input type=&quot;file&quot; class=&quot;w-full border border-gray-300 rounded px-4 py-2 focus:outline-none focus:border-primary&quot;
id=&quot;zip-file&quot; name=&quot;zip-file&quot; accept=&quot;.zip&quot; required&gt;
&lt;/div&gt;
&lt;div class=&quot;mb-4&quot;&gt;
&lt;label for=&quot;student-id&quot; class=&quot;text-primary font-semibold&quot;&gt;If you are a student, please enter your valid ID card
to get an additional student discount rate from us.&lt;/label&gt;
&lt;input type=&quot;file&quot; class=&quot;w-full border border-gray-300 rounded px-4 py-2 focus:outline-none focus:border-primary&quot;
id=&quot;student-id&quot; name=&quot;student-id&quot;&gt;
&lt;/div&gt;
&lt;button type=&quot;submit&quot; class=&quot;bg-primary text-white py-2 px-4 rounded-full hover:bg-blue-700&quot; id=&quot;submit-button&quot;&gt;Submit&lt;/button&gt;
&lt;/form&gt;
&lt;script&gt;
// Replace &#39;your_script_id_here&#39; with your actual Google Apps Script Web App URL
let url = &quot;https://script.google.com/macros/s/your_script_id_here/exec&quot;;
let form = document.getElementById(&quot;customer-form&quot;);
let zipFileInput = document.getElementById(&quot;zip-file&quot;);
let imageFileInput = document.getElementById(&quot;student-id&quot;);
form.addEventListener(&#39;submit&#39;, (e) =&gt; {
e.preventDefault(); // Prevent the default form submission
// Create a new FormData object
let formData = new FormData(form);
// Add the file uploads to the FormData
handleFileUpload(zipFileInput, formData);
handleFileUpload(imageFileInput, formData);
// Send the POST request using fetch
fetch(url, {
method: &quot;POST&quot;,
body: formData
})
.then(response =&gt; response.text())
.then(data =&gt; console.log(data))
.catch(error =&gt; console.error(error));
});
function handleFileUpload(fileInput, formData) {
let file = fileInput.files[0];
if (!file) return;
let fr = new FileReader();
fr.addEventListener(&#39;loadend&#39;, () =&gt; {
let res = fr.result;
let spt = res.split(&quot;base64,&quot;)[1];
let obj = {
base64: spt,
type: file.type,
name: file.name
};
formData.append(fileInput.name, file);
formData.append(&#39;file-info&#39;, JSON.stringify(obj));
});
fr.readAsDataURL(file);
}
&lt;/script&gt;

The Google sheets Appscript code that i used

  var jsonData = JSON.parse(e.postData.contents); // Parse the JSON data from the request
var spreadsheet = SpreadsheetApp.openById(&#39;1X57VuMPPN2mAIvbdbNCSCUdmfnQptor8E7i4tSmkjZ4&#39;);
var subSheetName = &#39;Cx input&#39;; // Replace with the name of your sub sheet
var subSheet = spreadsheet.getSheetByName(subSheetName);
if (!subSheet) {
subSheet = spreadsheet.insertSheet(subSheetName);
}
var rowData = [];
rowData.push(jsonData.email);
rowData.push(jsonData.name);
// Upload .stl or .zip file to Google Drive
var folderId = &#39;1iIxxTrYtwmlQPXn3qaAADFT-tUEVMZsT&#39;; // Replace with your Google Drive folder ID
var fileBlob = Utilities.newBlob(jsonData[&#39;zip-file&#39;], jsonData[&#39;zip-file&#39;].type, jsonData[&#39;zip-file&#39;].name); // Retrieve the file content from the JSON data and convert to Blob
var folder = DriveApp.getFolderById(folderId); // Get the folder by ID
var file = folder.createFile(fileBlob); // Create the file in the folder
var fileUrl = file.getUrl(); // Get the URL of the uploaded file
rowData.push(fileUrl); // Store the file URL in the spreadsheet
// Upload image file to Google Drive
var imageBlob = Utilities.newBlob(jsonData[&#39;student-id&#39;], jsonData[&#39;student-id&#39;].type, jsonData[&#39;student-id&#39;].name); // Retrieve the image content from the JSON data and convert to Blob
file = folder.createFile(imageBlob); // Create the file in the folder
fileUrl = file.getUrl(); // Get the URL of the uploaded image
rowData.push(fileUrl); // Store the image URL in the spreadsheet
subSheet.appendRow(rowData);
return ContentService.createTextOutput(&#39;Form submitted successfully&#39;);
}

The code is not being submitting properyly.
Console is giving this error.
Access to fetch at 'https://script.google.com/macros/s/your_script_id_here/exec' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Although I have doubled checked the permission, is to anyone. Still not working.

I want the form to successfully transfer the data to the google sheets and successfully upload the file to the drive.

答案1

得分: 1

我认为这实际上并不是一个CORS问题。我刚刚测试了您的代码,如您所述,我确实看到了您提出的CORS问题。如果我将您的doPost中除了最后的返回语句(return ContentService.createTextOutput(&#39;Form submitted successfully&#39;);)之外的所有代码都注释掉,那么fetch将成功,并且我会在控制台中看到Form submitted successfully的日志输出。除了在出现CORS问题时会看到CORS问题外,在谷歌脚本方面出现严重错误时也会出现CORS问题。

在这种情况下,我尚未测试您的所有谷歌脚本代码,但我认为它会立即在第一行var jsonData = JSON.parse(e.postData.contents);出失败。如果您按照当前方式进行fetch:

.fetch(url, {method: &quot;POST&quot;, body: formData})

那么我相信默认的contentType是url-encoded,所以数据不会存储在e.postData.contents中,正如文档所建议的那样。但可以通过e.parameter访问数据。很可能因为这个原因,您会遇到“尝试访问未定义的属性(contents)”的情况,然后导致CORS问题。

您可以直接从e.parameter获取数据,但我怀疑这样做可能无法捕获到您想要的文件数据。如果您想在e.postData内部正确获取数据,您可能需要修改您的fetch,类似于以下方式(根据此答案):

fetch(URL, {
  redirect: &quot;follow&quot;,
  method: &quot;POST&quot;,
  body: JSON.stringify(DATA),
  headers: {
    &quot;Content-Type&quot;: &quot;text/plain;charset=utf-8&quot;,
  },
})

尽管您可能需要根据您想要处理的文件数据进行修改。您的谷歌脚本中可能还有其他错误,所以我建议再次检查一下,但我认为最终的罪魁祸首是我上面提到的问题。

英文:

I think this is actually not a CORS issue. I just tested out your code and as is, I do see the CORS issue you brought up. If I comment out all the code in your doPost except for the final return statement (return ContentService.createTextOutput(&#39;Form submitted successfully&#39;);), the fetch succeeds and I see Form submitted successfully logging to the console. In addition to seeing a CORS issue when there is a CORS problem, you will also see a CORS issue if there is some fatal error on the google script side.

In this case, I haven't tested all your google script code, but I think it's failing right away on the first line var jsonData = JSON.parse(e.postData.contents);. If you do the fetch as you currently are:

.fetch(url, {method: &quot;POST&quot;, body: formData})

Then I believe the default contentType is url-encoded and so the data is not stored in e.postData.contents as the documentation suggests. The data can be accessed via e.parameter though. Most likely because of this you're getting into a trying to access a property (contents) of undefined situation, which then results in the CORS issue.

You could just grab the data from e.parameter, but I doubt that that would capture the file data you want. If you want to get the data properly within e.postData, you probably need to modify your fetch to something like this (per this answer):

fetch(URL, {
redirect: &quot;follow&quot;,
method: &quot;POST&quot;,
body: JSON.stringify(DATA),
headers: {
&quot;Content-Type&quot;: &quot;text/plain;charset=utf-8&quot;,
},
})

Although again you may need to modify this given you wanting to work with file data. It's possible that there are other errors in your google script, so I would double check that, but I think the ultimate culprit is what I mentioned above.

huangapple
  • 本文由 发表于 2023年7月20日 16:20:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76727951.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定