Could not find any info on my problem below - so posting.
I am uploading a BLOB to a google-apps-script webapp - code and log below.
e.postData
is missing on the webapp doPost(e)e.parameter.**NewsFile**
is missinge.contentLength
indicates the data is received - checked with 1Mb BLOBchrome.devtools
show correct payload sent to serverI am using FormData because I need to programatically attach files/blobs to the send request.
Any ideas/insight greatly appreciated.
// client code
function clientTest() {
const content = '<q id="a"><span id="b">hey!</span></q>';
const blob = new Blob([content], { type: "text/xml" });
const formdata = new FormData();
formdata.append("TestKey", "TestValue");
formdata.append("NewsFile", blob);
console.log(`client send info :: ${[...formdata.keys()].join(" | ")}`);
fetch("webappurl", { method: "POST", body: formdata });
}
// client log
// client send info :: TestKey | NewsFile
// server code - google apps script webapp
function doPost(e) {
console.info(`e.keys = ${[...Object.keys(e)].join(" | ")}`);
console.info(`param.keys = ${[...Object.keys(e.parameter)].join(" | ")}`);
console.info(`post.length = ${e.contentLength}`);
}
// server log
// e.keys = parameters | contextPath | parameter | contentLength | queryString | pathInfo
// param.keys = TestKey
// post.length = 684
In your client script, you wanted to request multipart/form-data
. Unfortunately, in the current stage, Web Apps cannot correctly receive the values of multipart/form-data
. In this case, your value is required to be sent as string data. When your showing script is modified, how about the following modification?
In this modification, it supposes that the data is a string data.
function clientTest() {
const content = '<q id="a"><span id="b">hey!</span></q>';
const obj = { content, "TestKey": "TestValue" };
fetch("webappurl", { method: "POST", body: JSON.stringify(obj) });
}
In the case of the above Javascript, the values content
and TestKey
can be retrieved as follows.
function doPost(e) {
// DriveApp.createFile("sample.txt", JSON.stringify(e)); // When you use this line, the event object can be seen as a text file.
const obj = JSON.parse(e.postData.contents);
const { content, TestKey } = obj;
return ContentService.createTextOutput("ok");
}
In this modification, it supposes that the data is a binary data.
function clientTest() {
const content = '<q id="a"><span id="b">hey!</span></q>';
const blob = new Blob([content], { type: "text/xml" });
const f = new FileReader();
f.readAsArrayBuffer(blob);
f.onload = d => {
const buf = new Int8Array(d.target.result);
const obj = { content: [...buf], mimeType: "text/xml", "TestKey": "TestValue" };
fetch("webappurl", { method: "POST", body: JSON.stringify(obj) });
}
}
In the case of the above Javascript, the values content
, mimeType
and TestKey
can be retrieved as follows.
function doPost(e) {
// DriveApp.createFile("sample.txt", JSON.stringify(e)); // When you use this line, the event object can be seen as a text file.
const obj = JSON.parse(e.postData.contents);
const { content, mimeType, TestKey } = obj;
DriveApp.createFile(Utilities.newBlob(content, mimeType, "sample"));
return ContentService.createTextOutput("ok");
}
When this script is run, the data is created in the root folder as a file.
In your showing script, it seems that Web Apps is used. When you modify the Google Apps Script of Web Apps, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful about this.
You can see the details of this in my report "Redeploying Web Apps without Changing URL of Web Apps (Author: me)".
From your following reply,
Ideal would if the e.parameter already contained all the fields
In this case, how about the following modification?
const content = '<q id="a"><span id="b">hey!</span></q>';
const blob = new Blob([content], { type: "text/xml" });
const f = new FileReader();
f.readAsArrayBuffer(blob);
f.onload = d => {
const buf = new Int8Array(d.target.result);
const obj = { content: JSON.stringify([...buf]), mimeType: "text/xml", "TestKey": "TestValue" };
const body = new FormData();
Object.entries(obj).forEach(([k, v]) => body.append(k, v));
fetch("webappurl", { method: "POST", body });
}
function doPost(e) {
// DriveApp.createFile("sample.txt", JSON.stringify(e)); // When you use this line, the event object can be seen as a text file.
const { content, mimeType, TestKey } = e.parameter;
DriveApp.createFile(Utilities.newBlob(JSON.parse(content), mimeType, "sample"));
return ContentService.createTextOutput("ok");
}
content, mimeType, TestKey
can be retrieved from e.parameter
.content
is large, this approach might not be able to be used. Please be careful about this. So, please confirm it in your situation.