Save a canvas image to google drive.

1,023 views
Skip to first unread message

Jonathan Butler

unread,
Apr 19, 2019, 5:30:00 PM4/19/19
to Google Apps Script Community

I need help saving a canvas image to drive. It should have been pretty straight forward. First encode the url using the "toDataURL" function. Whenever I submit the data to be decoded by the function the file continuously comes out corrupted. Any help would be appreciated.I'm wondering why the file always comes out corrupted.


Below is the html size of things

var canvas = document.getElementById('a');
var url = canvas.toDataURL("image/png")
var finalUrl = url.replace(/^data:image\/(png|jpg);base64,/, "")
google.script.run.withSuccessHandler(completed).submitApproval(finalUrl);

Below is my google-apps-script code

var contentType = 'image/png'
  var caseNumb = studentInfo['UserInfo']['Case Number'];
  //var data = urlData.split(',')[1];
  var imageData = Utilities.base64Decode(urlData);
  var blob =  Utilities.newBlob(imageData,MimeType.PNG);
  var folder = DriveApp.getFolderById(studentInfo['FolderID']);
  var file = folder.createFile("signature", blob, contentType);

The file gets created fine, but it's always corrupted.

Kanshi Tanaike

unread,
Apr 19, 2019, 8:00:43 PM4/19/19
to Google Apps Script Community
Can you provide the script for replicating your issue, because I couldn't find the issue from your script?

Jonathan Butler

unread,
Apr 20, 2019, 2:19:06 AM4/20/19
to google-apps-sc...@googlegroups.com
Here it is. The file always comes out corrupted.

On Fri, Apr 19, 2019 at 8:00 PM Kanshi Tanaike <kanshi...@gmail.com> wrote:
Can you provide the script for replicating your issue, because I couldn't find the issue from your script?

--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.
Visit this group at https://groups.google.com/group/google-apps-script-community.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-apps-script-community/fd4918b7-c7ef-4826-8c4e-41377ec732c4%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Kanshi Tanaike

unread,
Apr 20, 2019, 8:28:10 AM4/20/19
to google-apps-sc...@googlegroups.com
Thank you for providing the script. I could confirm that your javascript is fine. I found a modification point of your Google Apps Script. About the method of "createFile()", when "blob" is used, please use as "createFile(blob)". So the modified script becomes as follows. Can you test this?

function saveImage(urlData) {
 
var imageData = Utilities.base64Decode(urlData);
 
var blob =  Utilities.newBlob(imageData, MimeType.PNG).setName("signature");
 
var folder = DriveApp.getRootFolder();
 
var file = folder.createFile(blob);
}

- Reference


Marcos Gomes

unread,
Apr 20, 2019, 9:46:38 AM4/20/19
to Google Apps Script Community
Hi, Tanaike

another thing...
When you take a graphic in Google Sheets, via script, the image comes with errors. The lines come black, even if they are of another color.
By capturing the image directly from the chart, this problem does not occur.

chart_save_hand.png

chart_script.png

Jonathan Butler

unread,
Apr 20, 2019, 3:45:47 PM4/20/19
to google-apps-sc...@googlegroups.com

Kanshi Tanaike Thank you so much for your help! I have confirmed that it works. I'm a big fan of your work on StackOverflow and GitHub and I appreciate you taking the time out to get back to me.


--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.
Visit this group at https://groups.google.com/group/google-apps-script-community.

Kanshi Tanaike

unread,
Apr 20, 2019, 7:15:21 PM4/20/19
to Google Apps Script Community
I'm glad your issue was resolved. Thank you, too.

Kanshi Tanaike

unread,
Apr 20, 2019, 7:17:24 PM4/20/19
to Google Apps Script Community
At first, if my comment for this thread occurs your issue, I have to apologize. Can I ask you about your comment?

  1. About "take a graphic in Google Sheets, via script, the image comes with errors.", I cannot understand. Can you provide the detail information including the flow and script for replicating your issue.
  2. And what are your images? About this, can you explain the detail information?

I apologize for my poor English skill.

Marcos Gomes

unread,
Apr 22, 2019, 7:07:30 AM4/22/19
to google-apps-sc...@googlegroups.com
Hi, Tanaike
My english is much more poor!  :D
Explaining the problem:
Chart images saved directly from the graphic are the same as displayed.
Same chart saved via script, render different.

saved directly from the graphic:
save_with_sheet.png

result:
save_with_sheet_chart_OK.png


saved via script, render different:
save_with_script_erro.png

Script:
function getChartToPNG() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var chartGroup = ss.getSheetByName("grafico_grupo");
  var chart = chartGroup.getCharts()[0].getAs(MimeType.PNG);
  var folder = DriveApp.getFolderById(_folder_ID_);
  folder.createFile(chart).setName("chart.png");
}
 

--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.
Visit this group at https://groups.google.com/group/google-apps-script-community.

Clark Lind

unread,
Apr 22, 2019, 7:49:38 AM4/22/19
to google-apps-sc...@googlegroups.com
Marcos, if it is of any help, I too also have had this problem:
1) Manual save (via chart -> Download as PNG):

FY19 Hiring Goal_ 175.png




2) Via script & via Publish Chart:

chart.png



I am still trying to resolve, so I have no solution for you. Just wanted you to know you are not alone. :)  It might be a bug, or it may require different scripting techniques/APIs.
I've also noticed that the manual save is different than the "Published" chart. The Published version also looks like #2, not #1.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-community+unsub...@googlegroups.com.

Kanshi Tanaike

unread,
Apr 22, 2019, 8:37:10 AM4/22/19
to Google Apps Script Community
Thank you for replying. I could understand about your issue. About this issue, I have no workarounds now. I apologize for my poor skill. If I found the workaround, I would like to report it. I apologize for this situation, again.

Clark Lind

unread,
Apr 22, 2019, 9:44:36 AM4/22/19
to Google Apps Script Community
In looking into this further, the problem could be caused (I'm guessing) is,  when a user manually downloads a chart as PNG, this conversion is being done on the server with server-side code. However, Google charts are rendered in the browser. So, similar to what was done above (Converting canvas image to png). So adding Kanshi's code from above to Marcos' code might look something like this?

(I will test and see if this makes any difference in my charts.)


function getChartToPNG() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var chartGroup = ss.getSheetByName("grafico_grupo");
  var chart = chartGroup.getCharts()[0];
  var imageData = Utilities.base64Decode(chart);
  var blob =  Utilities.newBlob(imageData, MimeType.PNG).setName("chart.png");
  var folder = DriveApp.getFolderById(_folder_ID_);
  folder.createFile(blob);
}

Marcos Gomes

unread,
Apr 22, 2019, 10:05:35 AM4/22/19
to google-apps-sc...@googlegroups.com
Thanks, Clark

did not solve

--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.
Visit this group at https://groups.google.com/group/google-apps-script-community.

Clark Lind

unread,
Apr 22, 2019, 10:11:47 AM4/22/19
to Google Apps Script Community
No, it didn't help :(  Sorry.


On Monday, April 22, 2019 at 10:05:35 AM UTC-4, marcos.gomes wrote:
Thanks, Clark

did not solve

Em seg, 22 de abr de 2019 às 10:44, Clark Lind <cwl...@gmail.com> escreveu:
In looking into this further, the problem could be caused (I'm guessing) is,  when a user manually downloads a chart as PNG, this conversion is being done on the server with server-side code. However, Google charts are rendered in the browser. So, similar to what was done above (Converting canvas image to png). So adding Kanshi's code from above to Marcos' code might look something like this?

(I will test and see if this makes any difference in my charts.)

function getChartToPNG() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var chartGroup = ss.getSheetByName("grafico_grupo");
  var chart = chartGroup.getCharts()[0];
  var imageData = Utilities.base64Decode(chart);
  var blob =  Utilities.newBlob(imageData, MimeType.PNG).setName("chart.png");
  var folder = DriveApp.getFolderById(_folder_ID_);
  folder.createFile(blob);
}



On Monday, April 22, 2019 at 8:37:10 AM UTC-4, Kanshi Tanaike wrote:
Thank you for replying. I could understand about your issue. About this issue, I have no workarounds now. I apologize for my poor skill. If I found the workaround, I would like to report it. I apologize for this situation, again.

--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-community+unsub...@googlegroups.com.

Kanshi Tanaike

unread,
Apr 22, 2019, 7:31:12 PM4/22/19
to Google Apps Script Community
How about this workaround? In this workaround, I used Slides. The flow of this workaround is as follows.

1. Retrieve a chart from a sheet on Spreadsheet.
2. Create new Slides as a temporal.
3. Insert the chart to the created Slides as an image.
4. Retrieve the inserted image as a blob.
5. Save the blob as a file.
6. Move the temporal Slides to trash.

function getChartToPNG() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var chartGroup = ss.getSheetByName("Sheet1");
  var chart = chartGroup.getCharts()[0];
  var slides = SlidesApp.create("sample");
  var slide = slides.getSlides()[0];
  var image = slide.insertSheetsChartAsImage(chart);
  DriveApp.createFile(image.getBlob()).setName("chart.png");
  DriveApp.getFileById(slides.getId()).setTrashed(true);
}

In my environment, I thought that this might be able to be used. But if this was not useful for your situation, I apologize.

Clark Lind

unread,
Apr 23, 2019, 3:31:09 PM4/23/19
to Google Apps Script Community
Very ingenious. I will see if it works.

Clark Lind

unread,
Apr 23, 2019, 4:13:17 PM4/23/19
to Google Apps Script Community
That works, but not as expected. Something with the chart/embed using code inserts the bad quality version. So instead of creating a new slide and deleting every time, I created a permanent slide. In this slide, I inserted the sheets chart (which looks good quality). Then I proceed similar to your code with minor adjustments:

function getChartToPNG() {
  var slides = SlidesApp.openById("**Slide ID**");

 
var slide = slides.getSlides()[0];

 
var charts = slide.getSheetsCharts();
 
var image = DriveApp.createFile(charts[0].asImage()).setName("chart.png");
//I use to auto-update a Sites Page:
 
var page = SitesApp.getPageByUrl('Old Sites URL');
 
var atch = page.getAttachments();
  atch
[0].setFrom(image);  
}

Because the slide is linked to the sheets chart, it will be updated automatically.

Thank you Kanshi, this works!

Clark Lind

unread,
Apr 23, 2019, 6:10:34 PM4/23/19
to Google Apps Script Community
So, as a workaround:

1) In Sheets, select the chart you want as an image, and publish it.
2) In Slides, create a slide to hold the chart, and insert chart from sheets (find your published chart)
3) Keep the link between chart and slide so any time the sheet is updated, the chart is updated in the slide
4) The code below can then be set on whatever trigger you want. It will over-write the chart.png file inside drive, and you can do anything with it from there.
Reply all
Reply to author
Forward
Message has been deleted
0 new messages