How to preview an image located on a Google Drive using GAS - google-apps-script

I want to show a preview of a file (located on Google Drive) selected from a list or tree.
If I try to display an image file the image doesn't show up (allthough it is the right fileId)
function doGet()
{
var app = UiApp.createApplication().setTitle("Image");
var urlDrive = 'https://drive.google.com/file/d/0BxjtiwHnjnkrUVFKaWVaM3BNZjg';
var urlWeb = 'http://cdn.ndtv.com/tech/images/gadgets/google_webfonts_ap.jpg';
// var url = urlWeb; // works
var url = urlDrive; // Doe NOT work
var image = app.createImage(url).setHeight(200);
var panel = app.createVerticalPanel();
panel.add(image);
app.add(panel)
return app;
}
The example shows that changing the url to a file not present on Google Drive it works.
In general I would like to know if it is possible to preview a file (including msWord, msExcel and pdf) in a panel using GAS. A small example will be appreciated much of course.

The problem is the way you get the url.
The only url that works in this case is the one you can see when you examine the image file with "details" in your drive browser window.
it is actually build differently but contains the ID so it is quite easy to re-build...
Here is how it goes:
function doGet(){
var app = UiApp.createApplication().setTitle("Image");
var imgFile = DriveApp.getFilesByName('Chrysanthemum.jpg').next()
ID = imgFile.getId();
Logger.log(ID);
var imgUrl = 'https://googledrive.com/host/'+ID
var image = app.createImage(imgUrl).setHeight(200);
var panel = app.createVerticalPanel();
panel.add(image);
app.add(panel)
return app;
}
test here
EDIT :
Since the code above seems not to work for files that are not publicly shared (not sure) here is another way to get the result (test app updated) that works with files that are shared to 'anyone with the link can view'.
Note That this is not logical since the app is deployed to run "as me" and is accessible to anyone even anonymous"... so from the G Drive pov I open the file... go figure why it behave like that ;-)
I tested in an anonymous session and it works.
I hope this solution will be suitable for you.
function doGet(){
var app = UiApp.createApplication().setTitle("Image");
var imgFile = DriveApp.getFilesByName('Chrysanthemum.jpg').next()
var ID = imgFile.getId();
Logger.log(ID);
var imgUrl = 'https://drive.google.com/uc?export=view&id='+ID
// var imgUrl = 'https://googledrive.com/host/'+ID; //for public files apparently
var image = app.createImage(imgUrl).setHeight(200);
var panel = app.createVerticalPanel();
panel.add(image);
app.add(panel)
return app;
}

Related

I can´t upload documents to Google Sites from url using Apps Scripts

I am trying to upload files to Google Sites using the Url from my G-Drive. I am using this code, it is running but when I refresh the site the files don´t upload.
function uploadFiles(url, h) {
try {
var url = "myFileUrl";
var site = SitesApp.getSite("mySite", "myPage");
var page = site.getAllDescendants()[0];
var id = getIdFrom(url); // function that I have that gives you the id of an url
var blob = DriveApp.getFileById(id).getBlob();
var attachment = page.addHostedAttachment(blob);
return attachment.getUrl();
}
catch(error)
{
return error.toString();
}
There was no error when I ran it. I already solved this problem with a code bellow, but now I have a new one. When I upload the file it uploads as a .html file, and I want to upload it as .pptx or . xls depending on what type of document it is.
function uploadblob() {
var url = "myFileUrl;
var site = SitesApp.getSite("mySite", "myPage");
var page = site.getAllDescendants()[0];
var blob = UrlFetchApp.fetch(url).getBlob();
var attach = page.addHostedAttachment(blob);
}

Convert a gdoc into image

is there a way to create an image (e.g. a png) from a google document?
I really mean an image, not just a pdf. GetAS only creates pdf, but returns an error if contentType is set to image/png or other equivalent formats.
My (actually trivial) code is
function convertFile() {
var SOURCE_TEMPLATE = "1HvqYidpUpihzo_HDAQ3zE5ScMVsHG9NNlwPkN80GHK0";
var TARGET_FOLDER = "1Eue-3tJpE8sBML0qo6Z25G0D_uuXZjHZ";
var source = DriveApp.getFileById(SOURCE_TEMPLATE);
var targetFolder = DriveApp.getFolderById(TARGET_FOLDER);
var target = source.makeCopy(source,targetFolder);
var newFile = DriveApp.createFile(target.getAs('image/png'));
}
When I run this code, I get the following error (my translation):
The conversion from application/vnd.google-apps.document to image/png is not supported.
Ty
How about this answer?
Reason of error:
makeCopy() returns File object. getAs() cannot be used for this. By this, the error occurs.
Workaround:
Unfortunately, in the current stage, Google Document cannot be directly exported as PNG images. So it is required to think of workarounds. Google Document can be converted to PDF. This answer uses this. As a workaround, I would like to propose to use an external API which is ConvertAPI. I thought that using the external API, the script becomes simple. This a method (PDF to PNG API) of API can be converted from PDF data to PNG data.
When you try this, for example, you can also test this using "Free Package". When you try using "Free Package", please Sign Up at "Free Package" and retrieve your Secret key.
Sample script:
Before you run this script, please retrieve your Secret key and set it.
var secretkey = "###"; // Please set your secret key.
var SOURCE_TEMPLATE = "1HvqYidpUpihzo_HDAQ3zE5ScMVsHG9NNlwPkN80GHK0";
var TARGET_FOLDER = "1Eue-3tJpE8sBML0qo6Z25G0D_uuXZjHZ";
var url = "https://v2.convertapi.com/convert/pdf/to/png?Secret=" + secretkey;
var options = {
method: "post",
payload: {File: DriveApp.getFileById(SOURCE_TEMPLATE).getBlob()},
}
var res = UrlFetchApp.fetch(url, options);
res = JSON.parse(res.getContentText());
res.Files.forEach(function(e) {
var blob = Utilities.newBlob(Utilities.base64Decode(e.FileData), "image/png", e.FileName);
DriveApp.getFolderById(TARGET_FOLDER).createFile(blob);
});
References:
makeCopy()
getAs()
ConvertAPI
PDF to PNG API of ConvertAPI
Updated on January 11, 2023:
In the current stage, Google Apps Script can use V8 runtime. By this, there are some Javascript libraries that can be used with Google Apps Script. Ref1, Ref2 In this question, in the current stage, by using pdf-lib, all pages in a PDF file can be converted to PNG images using Google Apps Script. The sample script is as follows.
Sample script:
This method uses Drive API. Please enable Drive API at Advanced Google services.
Please set SOURCE_TEMPLATE and TARGET_FOLDER, and run main().
/**
* This is a method for converting all pages in a PDF file to PNG images.
* PNG images are returned as BlobSource[].
* IMPORTANT: This method uses Drive API. Please enable Drive API at Advanced Google services.
*
* #param {Blob} blob Blob of PDF file.
* #return {BlobSource[]} PNG blobs.
*/
async function convertPDFToPNG_(blob) {
// Convert PDF to PNG images.
const cdnjs = "https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.min.js";
eval(UrlFetchApp.fetch(cdnjs).getContentText()); // Load pdf-lib
const setTimeout = function (f, t) { // Overwrite setTimeout with Google Apps Script.
Utilities.sleep(t);
return f();
}
const data = new Uint8Array(blob.getBytes());
const pdfData = await PDFLib.PDFDocument.load(data);
const pageLength = pdfData.getPageCount();
console.log(`Total pages: ${pageLength}`);
const obj = { imageBlobs: [], fileIds: [] };
for (let i = 0; i < pageLength; i++) {
console.log(`Processing page: ${i + 1}`);
const pdfDoc = await PDFLib.PDFDocument.create();
const [page] = await pdfDoc.copyPages(pdfData, [i]);
pdfDoc.addPage(page);
const bytes = await pdfDoc.save();
const blob = Utilities.newBlob([...new Int8Array(bytes)], MimeType.PDF, `sample${i + 1}.pdf`);
const id = DriveApp.createFile(blob).getId();
Utilities.sleep(3000); // This is used for preparing the thumbnail of the created file.
const link = Drive.Files.get(id, { fields: "thumbnailLink" }).thumbnailLink;
if (!link) {
throw new Error("In this case, please increase the value of 3000 in Utilities.sleep(3000), and test it again.");
}
const imageBlob = UrlFetchApp.fetch(link.replace(/\=s\d*/, "=s1000")).getBlob().setName(`page${i + 1}.png`);
obj.imageBlobs.push(imageBlob);
obj.fileIds.push(id);
}
obj.fileIds.forEach(id => DriveApp.getFileById(id).setTrashed(true));
return obj.imageBlobs;
}
// Please run this function.
async function myFunction() {
const SOURCE_TEMPLATE = "1HvqYidpUpihzo_HDAQ3zE5ScMVsHG9NNlwPkN80GHK0";
const TARGET_FOLDER = "1Eue-3tJpE8sBML0qo6Z25G0D_uuXZjHZ";
// Use a method for converting all pages in a PDF file to PNG images.
const blob = DriveApp.getFileById(SOURCE_TEMPLATE).getBlob();
const imageBlobs = await convertPDFToPNG_(blob);
// As a sample, create PNG images as PNG files.
const folder = DriveApp.getFolderById(TARGET_FOLDER);
imageBlobs.forEach(b => folder.createFile(b));
}
When this script is run, all pages of the inputted PDF file are converted to PNG images, and those images are created in the destination folder.
Note:
I think that the above script works. But, in this case, when you directly copy and paste the Javascript retrieved from https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.min.js to your Google Apps Script project, the process cost for loading it can be reduced.
References:
pdf-lib
copyPages of pdf-lib
addPage of pdf-lib
I know this is an older question, but I thought I'd answer, since I believe I've found a solution that doesn't involve paying for a third-party subscription.
This can be accomplished by accessing the thumbnail of the Doc and creating a new PNG file from that thumbnail. Try this:
function convertFile() {
var SOURCE_TEMPLATE = "1HvqYidpUpihzo_HDAQ3zE5ScMVsHG9NNlwPkN80GHK0";
var TARGET_FOLDER = "1Eue-3tJpE8sBML0qo6Z25G0D_uuXZjHZ";
var source = DriveApp.getFileById(SOURCE_TEMPLATE).getThumbnail().getAs('image/png');
var targetFolder = DriveApp.getFolderById(TARGET_FOLDER);
TARGET_FOLDER.createFile(source);
}
However, I've found that getting the thumbnail of the Doc is not as high quality as getting the thumbnail of a PDF created from the Doc. You can try the code below to compare which version of the new PNG you prefer.
To do this, you will also need to enable Advanced Services on your project, specifically the Drive API service. To do this, follow these instructions to add a new Service to your Google Apps Script project:
Open the Apps Script project.
At the left, click Editor < >.
At the left, next to Services, click Add a service +.
Select Drive API and click Add.
Once you do that, you'll be able to use the Drive command in your script, which is different than DriveApp. Note also the update to source.makeCopy() to only include the TARGET_FOLDER:
function convertFile() {
var SOURCE_TEMPLATE = "1HvqYidpUpihzo_HDAQ3zE5ScMVsHG9NNlwPkN80GHK0";
var TARGET_FOLDER = "1Eue-3tJpE8sBML0qo6Z25G0D_uuXZjHZ";
var source = DriveApp.getFileById(SOURCE_TEMPLATE);
var targetFolder = DriveApp.getFolderById(TARGET_FOLDER);
var target = source.makeCopy(targetFolder);
var pdfBlob = target.getAs(MimeType.PDF);
var newPDF = TARGET_FOLDER.createFile(pdfBlob).setName('Some Name.pdf');
var newId = newPDF.getId();
Drive.Files.update({
title: newPDF.getName(), mimeType: MimeType.PDF
}, newId, pdfBlob);
var newFile = DriveApp.getFileById(newId).getThumbnail().getAs('image/png');
TARGET_FOLDER.createFile(newFile);
target.setTrashed(true);
newPDF.setTrashed(true);
}
This code will create a copy of your Google Doc file, convert it to a PDF, then grab the thumbnail of the PDF as a PNG, and then delete the copy of the Doc file and the PDF that were created.
The Drive.Files.update() function is the critical part of this code, as it finalizes the creation of the PDF file in your Drive. Trying to run the code without that portion will just return the new PDF file as null since the new PDF hasn't completely finished being created at that point.
Hope this helps!

How to get url for image file in google drive

I attempted to insert jpg images stored in a Google Drive folder into a spreadsheet using the script below. The Url I get using the getUrl() method does not work. However if I use this url to open the image in Chrome and right click on the image and choose 'Get image URL,' I get a Url that does work. Is there a script method that will get me the correct Url? Or is there another way of accomplishing the same result?
function testInsertImage() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var folder = DocsList.getFolder('DataBasePicts');
var files = folder.getFiles();
var img = files[0].getUrl();
sheet.insertImage(img, 2, 2); // In Class Sheet method 'insertImage(url, column, row)'
}
// Url obtained by the .getUrl() above which does not work
// "https://docs.google.com/open?id=1fxx_KYV46swKQk5vh9h1ideOhW76ZhJVYIPUjopbXm4"
// Url obtained by right clicking the image when opened in Chrome using above Url which does work
// "https://lh6.googleusercontent.com/eWA2oIabdGeXLnIRkTkdXuZFlvt6L_pJbgKBLoTFVDEWVESPxpvziHJnFpeXocMmnwUEvYWIab4=w1318-h612"
//.insertImage gives this error message:
// Error retrieving image from URL or bad URL: https://docs.google.com/open?
The Advanced Drive Service enables use of the Google Drive Web API from Google Apps Script. Once you've enabled the service by following these instructions, its methods and properties will show up in the GAS editor's Autocomplete feature, making it easy to explore the available capabilities.
For instance, an ADS File object has a collection of properties documented here. The one you're interested in is .webContentLink. We can easily combine ADS with the DriveApp methods that replaced the deprecated DocsList, for instance by retrieving the fileId of the image you're interested in and using it with the ADS get() function.
function testInsertImage() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var folders = DriveApp.getFoldersByName('DataBasePicts');
if (folders.hasNext()) {
// Assume folder name is unique, so use first match
var folder = folders.next();
var files = folder.getFiles();
if (files.hasNext()) {
// For this test, use first found file
var file = files.next();
var img = Drive.Files.get(file.getId()).webContentLink;
sheet.insertImage(img, 2, 2); // In Class Sheet method 'insertImage(url, column, row)'
}
// else error: no file found
}
// else error: no folder found
}
use getWebContentLink() method of File.
File file = serive.files().get(fileId).execute();
file.getWebContentLink()

Can we change a picture in a Google Doc dynamically?

I am coding a contract application in Google App Script.
It creates a GoogleDoc from a template that include an image of the seller's signature and initials.
As there are five seller, and a dozen different templates, is there a way to change the image of signature and initials?
I have no clues where to start looking for that.
thanks and have a nice day!
Eric
EDIT : I found something about InlineImage in DocumentApp... still looking
Here is a little code which appends a an image in a Google doc. Hope this will give you Idea to get going.
Similar concept I used to make a resume builder application which replaces Profile picture and a signature image
//Make a UI form to upload Image
function doGet() {
var app = UiApp.createApplication();
//Form
var form = app.createFormPanel().setEncoding('multipart/form-data').setId('form');
//Add this form to the application
app.add(form);
//Panel to hold form elements
var panel = app.createVerticalPanel();
//add this panel inside form
form.add(panel);
//Now create form elemnts
var label1 = app.createLabel('Upload Image');
var uploadControl = app.createFileUpload().setName('file').setId('file');
var submitBtn = app.createSubmitButton('Submit');
//Add all these elemnts to the panel
panel.add(label1).add(uploadControl).add(submitBtn);
//Return the application to the service URL
return app;
}
//This function is callend when the form is submitted
function doPost(e){
var fileBlob = e.parameter.file; //This is the image blob if an image is uploded
//Open the document
var doc = DocumentApp.openById('ID OF GOOGLE DOC')//change Id of the document
//get the body of document
var docBody = doc.getActiveSection();
//Append the iamge in document body
docBody.appendImage(fileBlob);
//Save and close the document
doc.saveAndClose();
}

Adding File to a Folder

I'm trying to relocate newly created Google Docs file to a folder within google drive (using Google Apps).
var newFile = DocumentApp.create('New File');
var newFileID = Docs.getFileById(newFile);
var newFileRelocated = newFileID.addToFolder(newFolder);
And I'm getting "Cannot find method addToFolder(. (Line ...)". What am I doing wrong? They method drops down as an option when I'm writing it and still it cannot find it.
It's likely that your newFolder is not what's expected. Is it a string? Where you defined it?
Anyway, the parameter expected in addToFolder must be a Folder object you got using some other method in DocsList. e.g. DocsList.getFolder("/path/to/folder") or DocsList.getFolderById("folder-id") and so on.
There seems to be other "inconsistencies" with your code, I'll paste what I you're trying to do:
var newDoc = DocumentApp.create('New Google Doc');
//a DocumentApp file and a DocsList file are not the same object, although they may point to the same Google Doc
var newFile = DocsList.getFileById(newDoc.getId());
var folder = DocsList.getFolder("/path/to/folder"); //I'm assuming the folder already exists
newFile.addToFolder(folder);
The logic of this is not exactly as you tried...
here is a working example :
function myFunction() {
var newFile = DocumentApp.create('New File');
var newFileID = newFile.getId()
var newFolder = DocsList.createFolder('test Folder')
DocsList.getFileById(newFileID).addToFolder(newFolder)
}
Just to add to this, I recently dealt with this issue.
I noticed the default location is to store the DocsList.create() file in the root folder (aka My Drive).
This could lead to a real headache if you were doing lots of files.
I added this as the line after the .addToFolder()
newFile.removeFromFolder(DocsList.getRootFolder());
The following function is a simple google script to pass in an image URL.
function fetchImageToDrive_(imageUrl)
{
//Fetch image blob
var imageBlob = UrlFetchApp.fetch(imageUrl).getBlob();
//Create image file in drive
var folder = DocsList.getFolder('test Folder');
folder.createFile(imageBlob);
}