英文:
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.
<div class="mb-4">
<label for="email" class="text-primary font-semibold">Email *</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">Name *</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">Please upload your zip file (.stl format only) which you
want to print.</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">If you are a student, please enter your valid ID card
to get an additional student discount rate from us.</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">Submit</button>
</form>
<script>
// Replace 'your_script_id_here' with your actual Google Apps Script Web App URL
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(); // 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: "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>
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('1X57VuMPPN2mAIvbdbNCSCUdmfnQptor8E7i4tSmkjZ4');
var subSheetName = 'Cx input'; // 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 = '1iIxxTrYtwmlQPXn3qaAADFT-tUEVMZsT'; // Replace with your Google Drive folder ID
var fileBlob = Utilities.newBlob(jsonData['zip-file'], jsonData['zip-file'].type, jsonData['zip-file'].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['student-id'], jsonData['student-id'].type, jsonData['student-id'].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('Form submitted successfully');
}
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('Form submitted successfully');
)之外的所有代码都注释掉,那么fetch
将成功,并且我会在控制台中看到Form submitted successfully
的日志输出。除了在出现CORS问题时会看到CORS问题外,在谷歌脚本方面出现严重错误时也会出现CORS问题。
在这种情况下,我尚未测试您的所有谷歌脚本代码,但我认为它会立即在第一行var jsonData = JSON.parse(e.postData.contents);
出失败。如果您按照当前方式进行fetch:
.fetch(url, {method: "POST", body: formData})
那么我相信默认的contentType是url-encoded
,所以数据不会存储在e.postData.contents
中,正如文档所建议的那样。但可以通过e.parameter
访问数据。很可能因为这个原因,您会遇到“尝试访问未定义的属性(contents)”的情况,然后导致CORS问题。
您可以直接从e.parameter
获取数据,但我怀疑这样做可能无法捕获到您想要的文件数据。如果您想在e.postData
内部正确获取数据,您可能需要修改您的fetch,类似于以下方式(根据此答案):
fetch(URL, {
redirect: "follow",
method: "POST",
body: JSON.stringify(DATA),
headers: {
"Content-Type": "text/plain;charset=utf-8",
},
})
尽管您可能需要根据您想要处理的文件数据进行修改。您的谷歌脚本中可能还有其他错误,所以我建议再次检查一下,但我认为最终的罪魁祸首是我上面提到的问题。
英文:
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('Form submitted successfully');
), 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: "POST", 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: "follow",
method: "POST",
body: JSON.stringify(DATA),
headers: {
"Content-Type": "text/plain;charset=utf-8",
},
})
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论