Google Spreadsheet Script: UrlFetchApp upload string as file - google-apps-script

I saw this SO thread to upload a file using UrlFetchApp.
Also I saw this SO thread to post a string as file in python requests (without having a file or creating a temp file).
I want to send a string as file in Google Spreadsheet Script, and based on the two threads above I think it should be possible to do it without creating a temp file in google drive.
My question is how in Google Spreadsheet Script I can pretend the string is coming from a file and pass it to UrlFetchApp?
Here is the base code I am working on:
var string = 'test';
var url = "https://api.telegram.org/.../sendDocument";
var chat_id = "12345";
var data = {'chat_id': chat_id,
'text':text} ;
var headers = { "Accept":"application/json",
"Content-Type":"application/json"
};
var options = { "method":"POST",
"headers": headers,
"payload" : payload
};
var response = UrlFetchApp.fetch(url, options);

Here is how I got it right to post a string as file:
var url = "https://api.telegram.org/.../sendDocument";
var blob = Utilities.newBlob('Test!', 'text/plain', 'report.txt');
var data = {
'chat_id' : '12345',
'document': blob
};
var options = {
'method' : 'POST',
'payload' : data,
};
UrlFetchApp.fetch(url, options);
Thanks to comment from #Jack Brown and google developer example for posting blobs (example titled: Make a POST request with form data.).

Related

documentapp.getactivedocument().getBlob gives pdf

i am trying to send the google document's content to my backend service.
In the app script i am using
if(host == 'sheets'){
var content = SpreadsheetApp.getActiveSpreadsheet().getBlob();
}else if (host == 'docs') {
var content = DocumentApp.getActiveDocument().getBlob();
}
I take the blob and sent it through multi part form request in URLFetchApp.fetch() through the payload parameter.
But the content for both the docs and sheets is converted/sent to my service as pdf.
Is there any way to preserve/send the files in google format itself ?
if not in google format then in Microsoft office formats ?
Best Regards,
Saurav
As mentioned in the similar post, this behavior is expected. If you want to get the file's content in Microsoft office formats,
you can check the following options:
(OPTION 1): Get export URL from Advanced Drive Service
Sample Code:
function getDocument(){
var host = "docs";
var fileId;
var exportFormat;
if(host == 'sheets'){
fileId = SpreadsheetApp.getActiveSpreadsheet().getId();
exportFormat = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
}else if (host == 'docs') {
fileId = DocumentApp.getActiveDocument().getId();
exportFormat = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
}
var url = Drive.Files.get(fileId).exportLinks[exportFormat];
Logger.log(url);
var oauthToken = ScriptApp.getOAuthToken();
var content = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + oauthToken
}
}).getBlob();
Logger.log(content.getContentType());
content.setName("TestFile");
MailApp.sendEmail("email#sample.com", "Test", "Test", {attachments: content});
}
Pre-requisite:
You need to enable Advanced Drive Service to get the export links of the file using Drive.Files.get(). This request will return a File Resource where you can get the exportLinks that can be accessed using a key based on the supported export MIME Types
What it does?
Depending on the host set, get the file id and export format based on supported export MIME Types
Get the file resource using Drive.Files.get() and get the export link based on the export format key set in step 1.
Use UrlFetchApp.fetch(url, params) and get the file's blob using HTTPResponse.getBlob()
Output:
(OPTION 2):Create export URL manually using the template url
Sample Code:
function getDocument(){
var host = "docs";
var fileId;
var url;
if(host == 'sheets'){
fileId = SpreadsheetApp.getActiveSpreadsheet().getId();
url = "https://docs.google.com/spreadsheets/export?id="+fileId+"&exportFormat=xlsx"
}else if (host == 'docs') {
fileId = DocumentApp.getActiveDocument().getId();
url = "https://docs.google.com/feeds/download/documents/export/Export?id="+fileId+"&exportFormat=docx";
}
Logger.log(url);
var oauthToken = ScriptApp.getOAuthToken();
var content = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + oauthToken
}
}).getBlob();
Logger.log(content.getContentType());
}
What it does?
Depending on the host set, get the file id and create an export link using this templates:
EXCEL: https://docs.google.com/spreadsheets/export?id=<fileId>&exportFormat=xlsx
WORD: https://docs.google.com/feeds/download/documents/export/Export?id=<fileId>&exportFormat=docx
Use UrlFetchApp.fetch(url, params) and get the file's blob using HTTPResponse.getBlob()
Note:
Based on Quotas for Google Services, Url Fetch Call has a daily quota of 20,000 for Consumer and G Suite free edition, while 100,000 for Google Workspace accounts

Post a file with urlFetchApp to a google web app

I am trying to post any type of file using Google Apps Script to a web app but I am not familiar with doPost.
My code looks like this:
function call(){
var file = getFile('/2.html'); //gets a file from my Google Drive (no point in posting all the code here for that)
var options = {
'method' : 'post',
'payload' : {file : file}
};
var response = UrlFetchApp.fetch('https://script.google.com/macros/s/AKfycbx0aIU_XjOHPXh0P6y2dTMmvGpI6WAuac_Cq5BOGw7nDLRlodT-/exec',options)
Logger.log(response)
This seems to work, although I have read I need to base64 encode a file for it to work properly. That's something I don't really understand.
On the web app side I made a doPost(e) but no matter what I tried to do with 'e' I can't work out what kind of object it is and how to process it. All I want to do really is to save it to Google Drive.
You may be wondering why I am going to these lengths to post the file to disk via a web app when I could save it directly. The reason is I am trying to do the process asynchronously using UrlFetchApp.fetchAll() so I can speed up the process of writing many files to disk at once.
If variable file is of type File, Get Blob from File and base64 encode it:
var options = {
'method' : 'post',
'payload' : Utilities.base64EncodeWebSafe(file.getBlob().getBytes())
};
On receiver web -app, Decode it back:
const doPost = e => {
const file = DriveApp.createFile(
Utilities.newBlob(
Utilities.base64DecodeWebSafe(
e.postData.contents
)
)
)
}
Thanks to #TheMaster. I made some modifications to the code because it resulted in an error because a file name was needed. you'll need your own apps script web app url to go here [APPS SCRIPT WEB APP URL]:
const doPost = e => {
const file = DriveApp.createFile(
Utilities.newBlob(
Utilities.base64DecodeWebSafe(
e.parameter.file
),e.parameter.contentType,e.parameter.fileName
)
)
}
function sendFile(file){
var fileName = file.getName();
var contentType = file.getBlob().getContentType();
var url = "[APPS SCRIPT WEB APP URL]";
var payload = {
fileName: fileName,
contentType : contentType,
file: Utilities.base64EncodeWebSafe(file.getBlob().getBytes())
};
var options = {
method: "POST",
payload: payload,
muteHttpExceptions : true,
};
var res = UrlFetchApp.fetch(url, options).getContentText();
}

getting active user name in Google sheets from external domain

I have a published web app:
function doGet(request) {
// DocumentApp.getActiveDocument();
SpreadsheetApp.getActive();
var about = Drive.About.get();
var user = about.name;
// Logger.log(Session.getActiveUser().getEmail());
return ContentService.createTextOutput(user);
}
... at this URL:
https://script.google.com/macros/s/AKfycbzTlhKJXrTAEPEba0l1KWqqzlkul2ntC-0iHi7_POj0wk7j3R6K/exec
Which produces the desired result the user's full name (after authorization to user's data is approved - subsequent running of the URL does not prompt for authentication or approval)
That is the data I want to retrieve from this App Script:
function Test3() {
var options = {
'method' : 'get',
'followRedirects' : true,
// 'validateHttpsCertificates' : 'true',
'muteHttpExceptions' : true,
'contentType' : 'null'
};
var url = "https://script.google.com/macros/s/AKfycbzTlhKJXrTAEPEba0l1KWqqzlkul2ntC-0iHi7_POj0wk7j3R6K/exec"
var response = UrlFetchApp.fetch(url, options);
// var response = test2() ;
// var myName = response.getContentText();
Browser.msgBox("[" + response + "]");
}
but I have not been able to get just that data. Instead I get an a page HTML text, which equates to a Google login page.
Again, just running the URL manually from a browser as any user results in the user name web page, so why when run from app script, it can't just retrieve the result of that page?
What am I missing? Surely I'm some simple syntax away from getting that data.

Using Google Apps Script and the Pastebin.com API to post a paste

I am trying to make a Pastebin.com paste using Google Apps Script from the spreadsheet script editor. Can anyone tell me what I'm doing wrong?
function postPastebinPost() {
var options, url, apiKey, payload, response;
apiKey = <api key goes here>;
payload = 'Hello World';
options = {
'method' : 'post',
'payload' : payload
};
url = 'https://pastebin.com/api/api_post.php'
+ '?api_dev_key=' + apiKey
+ '&api_option=paste'
+ '&api_paste_code=' + encodeURIComponent(payload);
response = UrlFetchApp.fetch(url, options);
Logger.log(response);
}
I run this and my log reads Bad API request, invalid api_option. I've searched for solutions but I have not found any.
Documentation:
• Pastebin.com API
• Google Apps Script's UrlFetchApp Class
The parameters should be passed in the payload of the POST request.
function postPastebinPost() {
var apiKey = 'YOUR KEY GOES HERE';
var text = 'Hello World';
var payload = {
api_dev_key: apiKey,
api_option: 'paste',
api_paste_code: text
};
var options = {
method : 'POST',
payload: payload
};
var url = 'https://pastebin.com/api/api_post.php';
var response = UrlFetchApp.fetch(url, options);
Logger.log(response.getContentText());
}
The following is in case the user wants to create a new paste as part of their own Pastebin account (and not «Paste as a guest»). It's just an adaptation of Amit Agarwal's answer.
function postPastebinPost() {
var title = 'abc';
var contents = 'Hello World \n next line of content \n more text';
var payload = {
api_dev_key: 'aa6f3ab...', // https://pastebin.com/api#1
api_option: 'paste',
api_paste_name: title,
api_paste_code: contents,
api_paste_private: '0', // public paste
api_user_name: 'diccionario...', // name of your Pastebin account
api_user_password: 'dk398d...', // password to your Pastebin account
api_user_key: '39dk3...', // https://pastebin.com/api/api_user_key.html
};
var options = {
method : 'POST',
payload: payload
};
var url = 'https://pastebin.com/api/api_post.php';
var response = UrlFetchApp.fetch(url, options);
Logger.log(response.getContentText());
}
The whole documentation is at https://pastebin.com/api.

Google Script UrlFetchApp.fetch returns a 404 eventhough the page exist

I am sending automated report with Google spreadsheet and Google script.
So far it was working perfectly. But somehow when I try to create a new report to be emailed, the function "UrlFetchApp.fetch" return a 404. The same situation happened when I tried copying the old report.
The line with "UrlFetchApp.fetch" give me this error:
Request failed for https://docs.google.com/spreadsheets/d/1qm_bCKn4MbLKy7AIuIeu7bTZcTk8ObYBln0GAxwfsX8/pub?gid=195635557&single=true&output=pdf returned code 404. Truncated server response
It seems that I am not the only one having the issue but I cannot find any solution to it.
Here is the code:
function emailSpreadsheetAsCSV() {
var ss = SpreadsheetApp.openById("1qm_bCKn4MbLKy7AIuIeu7bTZcTk8ObYBln0GAxwfsX8");
var url = ss.getUrl();
url = url.replace(/edit$/,'');
var token = ScriptApp.getOAuthToken();
var sheets = ss.getSheets();
//make an empty array to hold your fetched blobs
var blobs = [];
for (var i=0; i<sheets.length; i++) {
var response = UrlFetchApp.fetch("https://docs.google.com/spreadsheets/d/1qm_bCKn4MbLKy7AIuIeu7bTZcTk8ObYBln0GAxwfsX8/pub?gid=195635557&single=true&output=pdf", {
headers: {
'Authorization': 'Bearer ' + token
},
'muteHttpExceptions': false
});
//convert the response to a blob and store in our array
blobs[i] = response.getBlob().setName(sheets[i].getName() + '.csv');
}
//create new blob that is a zip file containing our blob array
var zipBlob = Utilities.zip(blobs).setName(ss.getName() + '.zip');
return blobs[0];
}
Thanks a lot for your help.
Aymeric.
I've gotten this problem too and after some research, Spence Easton (question 34573295) solved my issue. I simply added this bogus call to drive so access is granted, and so the script can now get to your file.
Add this near the top before trying to grab the url:
var bogus = DriveApp.getRootFolder();
Now it runs fine with no 404 errors.
Remove the headers from the request:
var response = UrlFetchApp.fetch("https://docs.google.com/spreadsheets/d/1qm_bCKn4MbLKy7AIuIeu7bTZcTk8ObYBln0GAxwfsX8/pub?gid=195635557&single=true&output=pdf", {
'muteHttpExceptions': false
});
Check if it works for you.
You use the "pub" url so are you sure the spreadsheet is published on the web ? If you get a 404 it means the page is not published.
If file is published the bearer is not necessary as it is public now.
After I don't really understand your code because you iterate all the sheets of your file
for (var i=0; i<sheets.length; i++)
but the param "gid" (pub?gid=195635557&single=true&output=pdf) for the url in your urlfetch is fixed ?
Second point you get the file as pdf and after you create a csv ?
Why not get the file as csv directly : https://docs.google.com/spreadsheets/export?id=TheIdOfTheFile&exportFormat=csv
By adapting this code you can get the csv directly, see : https://stackoverflow.com/a/28503601/3556215
Take care you will get the first page and not others.
Stéphane
Try with:
var response = UrlFetchApp.fetch(url, options);
var result = JSON.parse(res.getContentText());