I have base64 encoded png image which is placed in Google Sheet cell. Need to decode this in Google App Script to image and using following code.
=============================================================
CODE
var ss = SpreadsheetApp.getActiveSheet();
var strBase64Image = ss.getRange('F1').getValue()
ss.getRange('F2').setValue(strBase64Image); // test fn is working
var decodedBytes = Utilities.base64Decode(strBase64Image); // decode to byte array
var blobImg = Utilities.newBlob(decodedBytes, MimeType.PNG); // create blog from byte array
ss.insertImage(blobImg, 6, 3); // write image to F3 cell
=============================================================
ERROR
Exception: Could not decode string.
=============================================================
This base64 encoded png image string is getting decoded to image when tested in https://codebeautify.org/base64-to-image-converter
Thanks,
Nilesh Korde
Two things:
You need to strip off data:image/png;base64, from your Base64 string - the presence of this header is what gives you the error
Exception: Could not decode string.
When you create the blob, you need to give it a name: var blobImg = Utilities.newBlob(decodedBytes, MimeType.PNG, 'MyImageName'); - as featured in the sample code here.
Otherwise you will get the error
Exception: Unexpected error while getting the method or property insertImage on object SpreadsheetApp.Sheet..
Related
I'm receiving a callback from a server in my Google app script via doPost.
The problem is, my Json format is with a this word in front of the Json "Data=", because of that I'm not able to work with the Json callback.
The code:
Function doPost(e){
var r = e.postdata.contents
Logger.log(r)
}
I'm receiving the bellow format.
data={""retorno"":{""estoques"":[{""estoque"":{""codigo"":""001a"",""nome"":""M\u00e1scara 100% Algod\u00e3o Lav\u00e1vel Dupla Prote\u00e7\u00e3o - 10 Unidades"",""estoqueAtual"":50,""depositos"":[{""deposito"":{""id"":7939278964,""nome"":""Geral"",""saldo"":""50.0000000000"",""desconsiderar"":""N"",""saldoVirtual"":""50.0000000000""}}]}}]}}
Anyway to remove this "Data="?
Thanks
If you just want to remove the substring data= - the easiest would be to use the method silce()
Sample:
var r = e.postdata.contents;
var sliced = r.toString().slice(5);
Logger.log(slide);
How to parse a XML file stored in my google drive but which stands out as a html type ?!
I save on my google Drive cloud a copie of an xml of the source: http://api.allocine.fr/rest/v3/movie?media=mp4-lc&partner=YW5kcm9pZC12Mg&profile=large&version=2&code=265621
I can parsing the source but i cant'xml parsing the copie that look like a html type !!
i have parsing error like: The element type "meta" must be terminated by the matching end-tag ""
or Element type "a.length" must be followed by either attribute specifications, ">" or "/>"
I shared it on https://drive.google.com/file/d/16kJ5Nko-waVb8s2T12LaTEKaFY01603n/view?usp=sharing to give you an access and test my script.
I know that i can using cacheService and it works but for have other control of the buffering i woud try this way
function xmlParsingXmlStoreOnGoogleDrive(){
//So , this is the original xml that is good parsed
var fetched=UrlFetchApp.fetch("http://api.allocine.fr/rest/v3/movie?media=mp4-lc&partner=YW5kcm9pZC12Mg&profile=large&version=2&code=265621")
var blob=fetched.getBlob();
var getAs=blob.getAs("text/xml")
var data=getAs.getDataAsString("UTF-8")
Logger.log(data.substring(1,350)); // substring to not saturate the debug display this expected code XML:
/*
?xml version="1.0" encoding="utf-8"?>
<!-- Copyright © 2019 AlloCiné -->
<movie code="265621" xmlns="http://www.allocine.net/v6/ns/">
<movieType code="4002">Long-métrage</movieType>
<originalTitle>Mise à jour sur Google play</originalTitle>
<title>Mise à jour sur Google play</title>
<keywords>Portrait of a Lady on Fire </keywords>
*/
var xmlDocument=XmlService.parse(data);
var root=xmlDocument.getRootElement();
var keywords=root.getChild("keywords",root.getNamespace()).getText();
Logger.log(keywords); // Display the expected result :"Portrait of a Lady on Fire "
// And this my copie of the original xml, that i can't parsing
var fetched=UrlFetchApp.fetch("https://drive.google.com/file/d/1K3-9dHy-h0UoOOY5jYfiSoYPezSi55h1/view?usp=sharing")
var blob=fetched.getBlob();
var getAs=blob.getAs("text/xml")
var data=getAs.getDataAsString("UTF-8")
Logger.log(data.substring(1,350)); // substring to not saturate the debug display this non expected code HTML !:
/*
!DOCTYPE html><html><head><meta name="google" content="notranslate"><meta http-equiv="X-UA-Compatible" content="IE=edge;">
<style>#font-face{font-family:'Roboto';font-style:italic;font-weight:400;src:local('Roboto Italic'),local('Roboto-Italic'),
url(//fonts.gstatic.com/s/roboto/v18/KFOkCnqEu92Fr1Mu51xIIzc.ttf)format('truetype');}#font-face{font-fam......
*/
var xmlDocument=XmlService.parse(data); // ABORT WITH THE ERROR: Element type "a.length" must be followed by either attribute specifications, ">" or "/>"
var root=xmlDocument.getRootElement();
var keywords=root.getChild("keywords",root.getNamespace()).getText();
Logger.log(keywords);
}
I read on this similar ask :Parse XML file (which is stored on GoogleDrive) with Google app script
that "Unfortunately we can't directly get xml files in the google drive" !!
Is it right and would that simply mean that I can not realize my script?
You want to retrieve the data from the file on Google Drive and parse as XML data using XmlService.
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this answer?
Modification points:
About var fetched=UrlFetchApp.fetch("https://drive.google.com/file/d/16kJ5Nko-waVb8s2T12LaTEKaFY01603n/view?usp=sharing"), in this case, the file content cannot be retrieved from this endpoint. If you want to retrieve the file content with UrlFetchApp, please use the endpoint of https://drive.google.com/uc?id=16kJ5Nko-waVb8s2T12LaTEKaFY01603n&export=download. This is webContentLink.
When the file is in your Google Drive and/or shared publicly, you can retrieve the data with the script of DriveApp.getFileById(fileId).getBlob().getDataAsString().
Modified script:
For example, when your shared sample file of https://drive.google.com/file/d/16kJ5Nko-waVb8s2T12LaTEKaFY01603n/view?usp=sharing is used, the script becomes as follows.
Sample script 1:
In this pattern, the file content is retrieved from your shared file with UrlFetchApp.fetch().
var data = UrlFetchApp.fetch("https://drive.google.com/uc?id=16kJ5Nko-waVb8s2T12LaTEKaFY01603n&export=download").getContentText(); // Modified
var xmlDocument=XmlService.parse(data);
var root=xmlDocument.getRootElement();
var keywords=root.getChild("keywords",root.getNamespace()).getText();
Logger.log(keywords); // <--- You can see "Portrait of a Lady on Fire" at log.
In this case, the script is required to be shared publicly. If you want to retrieve the file content without sharing, please use the access token for requesting.
Sample script 2:
In this pattern, the file content is retrieved from your shared file with DriveApp.getFileById().
var fileId = "16kJ5Nko-waVb8s2T12LaTEKaFY01603n"; // Added
var data = DriveApp.getFileById(fileId).getBlob().getDataAsString(); // Added
var xmlDocument=XmlService.parse(data);
var root=xmlDocument.getRootElement();
var keywords=root.getChild("keywords",root.getNamespace()).getText();
Logger.log(keywords); // <--- You can see "Portrait of a Lady on Fire" at log.
16kJ5Nko-waVb8s2T12LaTEKaFY01603n of https://drive.google.com/file/d/16kJ5Nko-waVb8s2T12LaTEKaFY01603n/view?usp=sharing is the file ID.
In this case, the file is not required to be shared. But the file is required to be in your Google Drive.
References:
Files of Drive API
webContentLink: A link for downloading the content of the file in a browser using cookie based authentication. In cases where the content is shared publicly, the content can be downloaded without any credentials.
getFileById(id)
If I misunderstood your question and this was not the direction you want, I apologize.
Wonderful ! You are write. Your two suggestions are working.
I just made a mistake elsewhere in my code. So that solution 1 does not work anymore.
That is why give a new script to test it . For my training only, because my project is safe thanks to you :)
function storeXmlOnGoogleDriveThenParsIt(url){
url=url||"http://api.allocine.fr/rest/v3/movie?media=mp4-lc&partner=YW5kcm9pZC12Mg&profile=large&version=2&code=265621"; // to test
// on my Google Drive i make a copi of the url called. (This to preserve the server from too many request.)
var bufferedXml=DriveApp.getRootFolder().searchFolders('title = "BufferFiles"').next().createFile("xmlBuffered.xml", UrlFetchApp.fetch(url).getContentText(),MimeType.PLAIN_TEXT);
var urlBufferedXml=bufferedXml.getUrl() // The new url ,of the buffered file
var fileId=urlBufferedXml.match(/https:\/\/drive.google.com\/file\/d\/(.*)\/view.*/)[1];
//Now i want to pars the buffered xml file
//[ Your seconde way to get data is working perect ! THANK YOU A LOT !!!
var data = DriveApp.getFileById(fileId).getBlob().getDataAsString();
var xmlDocument=XmlService.parse(data);
var root=xmlDocument.getRootElement();
var mynamespace=root.getNamespace();
var keywords=root.getChild("keywords",root.getNamespace()).getText();
Logger.log("keywords:"+keywords) // and parsing success ]
//[ The first way to get data was ok BUT DAMNED it now aborting ! Since modifications on the line code that create the xml, and i cant' retrieve the right code
var downloadUrlBufferedXml="https://drive.google.com/uc?id="+fileId+"&export=download";
var data = UrlFetchApp.fetch(downloadUrlBufferedXml).getContentText(); // was good but now data is here again like a html text ! :(
Logger.log("data"+data.substring(1,350)); // this show that data is HTML type and not XML type ! :(
var xmlDocument=XmlService.parse(data); // So i have Error like: The element type "meta" must be terminated by the matching end-tag "</meta>" ]
var root=xmlDocument.getRootElement();
var mynamespace=root.getNamespace();
var keywords=root.getChild("keywords",root.getNamespace()).getText();
Logger.log("keywords:"+keywords)
}
I'm writing a Google Apps For Google Sheets. I want to read cell contents as a string and then parse it. In a cell I have a comma delimited list of IDs (e.g. "13,57,29"). Then I wrote a code that turns this into an array of strings (so "13,57,29" becomes ["13", "57", "29"]). So far I used this code:
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var blockedListString = data[0][0];
var blockedArray = blockedListString.split(",");
This works fine for the example I gave above. But I'm running into problem when the cell has only "13" in it. I get an error saying:
TypeError: cannot find function split in object 13.
So basically it seems like it stops being treated as a string and becomes something else (int?). The getValues() function returns an Object[][] so there's probably some indirect cast going on.
How can I fix that / force the cell to be read as string / force something to be cast to a string?
I'm receiving a base64encoded image in a Google Sheets script. I can successfully generate an image by logging
e.postData.contents
then using https://www.base64decode.org/ to decode and generate a .jpg file. But when I try to do the decoding inside the google script and write a jpg file to drive, it is corrupted. It looks similar, but there are some replacement characters inserted. Here's my code:
function doPost(e) {
var decoded = Utilities.base64Decode(e.postData.contents, Utilities.Charset.UTF_8);
var blob = Utilities.newBlob(decoded);
DriveApp.createFile('img_'+date+'.jpg', blob.getDataAsString('Windows-1252'), MimeType.JPEG);
}
I also tried blob.getAs('image/jpeg'), but that just returns a 4-byte file containing the text Blob.
Any ideas? I've tried a few different charsets, and Windows-1252 seems to give the closest results.
How about this sample script? When you use this, please define date. In my test, also I could confirm that the base64 encoded jpeg file could be decoded at https://www.base64decode.org/.
And when you updated doPost(), please be careful as follows. Please redeploy your script to Web Apps as a new version. If this is not carried out, script of the deployed Web Apps is not updated.
Sample script :
function doPost(e) {
var decoded = Utilities.base64Decode(e.parameters.contents, Utilities.Charset.UTF_8);
var blob = Utilities.newBlob(decoded, "image/jpeg", 'img_'+date+'.jpg'); // Please define date.
DriveApp.createFile(blob);
}
Curl sample :
If you want to try your doPost() using curl, you can use following command. When you use this, please input filename which is base64 encoded file and Web Apps URL.
curl -L -F "contents=`cat ### Filename ###`" "https://script.google.com/macros/s/#####/exec"
If I misunderstand your question, I'm sorry.
I am facing the same issue. my spreadsheet is showing an image but broken and unsupported. see the screenshot columns
I am sending the base64 image from autohotkey script. here is my autohotkey snippet:
Base64Enc(File="") { ; By SKAN / 18-Aug-2017 https://www.autohotkey.com/boards/viewtopic.php?t=35964
Local Rqd := 0, B64, B := "", N := 0 - LineLength + 1 ; CRYPT_STRING_BASE64 := 0x1
FileGetSize,nBytes,%File%
FileRead,Bin,*c %File%
DllCall( "Crypt32.dll\CryptBinaryToString", "Ptr",&Bin ,"UInt",nBytes, "UInt",0x1, "Ptr",0, "UIntP",Rqd )
VarSetCapacity( B64, Rqd * ( A_Isunicode ? 2 : 1 ), 0 )
DllCall( "Crypt32.dll\CryptBinaryToString", "Ptr",&Bin, "UInt",nBytes, "UInt",0x1, "Str",B64, "UIntP",Rqd )
B64:=StrReplace(B64,"`r`n")
return RTrim(B64,"`n")}
; Convert the screenshot to base64 encoded text
screenshotBase64 := Base64Enc(screenshotFile)
; Send the input, file attachment, and screenshot to the Google App Script
WinHttp := ComObjCreate("WinHttp.WinHttpRequest.5.1")
WinHttp.Open("POST", "https://script.google.com/macros/s/AKfycbypXKVB6DQi0xdWNjR1KM3q3A5w1flSedSkqHH3GpvlDCAirn9e_BOgUwhLbuf1LSEHZg/exec")
WinHttp.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
fileSize := StrLen("input=" . input . "&screenshot=" . screenshotBase64 . "&file=" . fileBase64 . "&filename=" . fileName)
;WinHttp.SetRequestHeader("Content-Length", fileSize)
WinHttp.Send("input=" . input . "&screenshot=" . screenshotBase64 . "&file=" . fileBase64 . "&filename=" . fileName)
; Get the response from the script and display it
response := WinHttp.ResponseText
msgbox % response
and this is my google app script code:
// Check if a screenshot was sent
if (screenshot) {
// Decode the base64 data
var decodedImage = Utilities.base64Decode(screenshot, Utilities.Charset.UTF_8) || null;
// Check if the decoded data is not null
if (decodedImage) {
// Create a timestamp for the filename
var timestamp = new Date().getTime();
// Create an image from the decoded data
var img = Utilities.newBlob(decodedImage, "image/jpeg", 'screenshot-'+timestamp+'.jpg');
// Get the folder where you want to upload the image
var folder = DriveApp.getFolderById("1Xmkr8vXTsTIQPMUr2UR1TpzJ2YtTHwOu");
// Upload the image to the folder and get the file object
var driveFile = folder.createFile(img,img.getDataAsString('Windows-1252'),);
// Make the file publicly accessible
driveFile.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.VIEW);
// Get the download URL of the file
imgUrl = "https://drive.google.com/uc?id="+driveFile.getId();
} else {
throw new Error("Error decoding base64 data.");
}
}
In google app scripts, the following line throws error:
DriveApp.createFile( e.parameter.fileupBlob);
Where fileupBlob is hidden field in the form with a BLOB stored in it.
Error thrown when executed:
Cannot find method createFile((class)). (line 23, file "Code", project
"saving")
The argument of DriveApp.createFile must be a blob.
The value returned by e.parameter.varName is a string.
Therefore the error you get. The only case when a blob is returned from a form is when you use a file upload widget, the hidden widget behaves like a text widget.
You need to create the blob as shown below. It is assuming you passed a valid blob. EDIT: If drive is having difficulty figuring out what type of file it is from the blob you can provide that info yourself. Another thought is that the blob may be base64 encoded. You may have to decode it before creating the new blob. You haven't posted any code so I can't tell what is going on.
var name = "fileName.png";
var contentType = "image/png";
var fileBlob = Utilities.newBlob(e.parameter.fileupBlob, contentType, name);
DriveApp.createFile(fileBlob);
Do this
let imageBlob = images[0].getBlob();
let name = 'fileName.jpeg';
let contentType = 'image/jpeg';
let fileBlob = Utilities.newBlob(imageBlob.getBytes(), contentType, name);
let imageFile = folder.createFile(fileBlob).setName('ravgeet.jpeg');
Got it! The javascript library was returning string dataURI and i replaced the first part of dataURI in jquery:
strDataURI=strDataURI.replace("data:image/png;base64,", "");
document.getElementById("blobobj").value = strDataURI;
Then i was able to create the image
var str=Utilities.base64Decode(e.blobobj);
var fileBlob = Utilities.newBlob(str).setContentType('image/png');