Unable to open FilePicker with Google App script - javascript

I was trying to use Google App Script. My first attempt concern the capability to open a file picker and select a file from my Google Drive. To do this, I read th official documentation and I try to implement it. So I write the following application:
Code.gs
function doGet() {
return HtmlService
/*.createTemplateFromFile('index.html')
.evaluate();*/
.createHtmlOutputFromFile('index.html');
}
index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript">
// The Browser API key obtained from the Google API Console.
// Replace with your own Browser API key, or your own key.
var developerKey = "{{developer-key}}";
// The Client ID obtained from the Google API Console. Replace with your own Client ID.
var clientId = "{{client-id}}"
// Replace with your own project number from console.developers.google.com.
// See "Project number" under "IAM & Admin" > "Settings"
var appId = "{{project-number}}";
// Scope to use to access user's Drive items.
var scope = ['https://www.googleapis.com/auth/drive'];
var pickerApiLoaded = false;
var oauthToken;
// Use the Google API Loader script to load the google.picker script.
function loadPicker() {
gapi.load('auth', {'callback': onAuthApiLoad});
gapi.load('picker', {'callback': onPickerApiLoad});
}
function onAuthApiLoad() {
window.gapi.auth.authorize(
{
'client_id': clientId,
'scope': scope,
'immediate': false
},
handleAuthResult);
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
}
// Create and render a Picker object for searching images.
function createPicker() {
if (pickerApiLoaded && oauthToken) {
var view = new google.picker.View(google.picker.ViewId.DOCS);
view.setMimeTypes("image/png,image/jpeg,image/jpg");
var picker = new google.picker.PickerBuilder()
.enableFeature(google.picker.Feature.NAV_HIDDEN)
.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId(appId)
.setOAuthToken(oauthToken)
.addView(view)
.addView(new google.picker.DocsUploadView())
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
alert('The user selected: ' + fileId);
}
}
</script>
</head>
<body>
<div id="result"></div>
<!-- The Google API Loader script. -->
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=loadPicker"></script>
</body>
</html>
When I try to execute the code, after the authorization phase, I obtain the a blank screen and a blank dialog with the error: Failed to execute 'postMessage'. What is wrong? Thanks

Issue/Solution:
You're working within a iframe, where content is served from a different origin. You should use setOrigin on the picker builder.
Snippet:
var picker = new google.picker.PickerBuilder()
//...
.setOrigin(google.script.host.origin)
Reference:
Working with Picker API
File Open Dialog Code Sample

Related

TypeError: gapi.client is undefined error while downloading files from file picker

I have implemented a google file picker in HTML and JS. I have created a client credentials and in the verge of downloading the files from file picker. My code is
<!DOTYPE html>
<html>
<head>
<title>My website</title>
<script type="text/javascript">
// The Browser API key obtained from the Google API Console.
var developerKey = '############################';
// The Client ID obtained from the Google API Console. Replace with your own Client ID.
var clientId = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
// Scope to use to access user's photos.
var scope = 'https://www.googleapis.com/auth/drive';
var appId = "1255s8a2s";
var pickerApiLoaded = false;
var oauthToken;
// Use the API Loader script to load google.picker and gapi.auth.
function onApiLoad() {
gapi.load('auth2', onAuthApiLoad);
gapi.load('picker', onPickerApiLoad);
gapi.client.load('drive', 'v2',handleClientLoad);
}
function handleClientLoad() {
gapi.client.setApiKey(apiKey);
window.setTimeout(onAuthApiLoad,1);
}
function onAuthApiLoad() {
var authBtn = document.getElementById('auth');
authBtn.disabled = false;
authBtn.addEventListener('click', function() {
gapi.auth2.authorize({
client_id: clientId,
scope: scope
}, handleAuthResult);
});
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
}
// Create and render a Picker object for picking user Photos.
function createPicker() {
if (pickerApiLoaded && oauthToken) {
var view = new google.picker.View(google.picker.ViewId.DOCS);
view.setMimeTypes("image/png,image/jpeg,image/jpg");
var picker = new google.picker.PickerBuilder().
enableFeature(google.picker.Feature.NAV_HIDDEN).
enableFeature(google.picker.Feature.MULTISELECT_ENABLED).
setOAuthToken(oauthToken).
setAppId(appId).
addView(view).
setDeveloperKey(developerKey).
setCallback(pickerCallback).
build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
var url = 'nothing';
var ids=[];
if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
var ln = data[google.picker.Response.DOCUMENTS];
for(i=0;i<ln.length;i++) {
ids[i] = data.docs[i].id;
gapi.client.drive.files.get({'fileId': ids[1]});
}
}
}
</script>
</head>
<body>
<h1> Welcome to detect the colours of your image </h1>
<p> Please upload required images. Let us detect what wonderful colours do your images have</p>
<form id="upload-form" action="{{ url_for('upload') }}" method = "POST" enctype="multipart/form-data">
<input type = "file" name="file" accept="image/*" multiple>
<input type="submit" value="upload">
</form>
<form method = "POST" action="/gdrive">
<button type="button" id="auth">upload from google</button>
</form>
<div id="result"></div>
<!-- The Google API Loader script. -->
<script src="https://apis.google.com/js/platform.js?onload=init" async defer></script>
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=loadPicker"></script>
</body>
</html>
After reading google drive javascript api gapi.client.drive.files undefined, I decided to add gapi.client.load('drive', 'v2', callback); in my code. However the result remains the same. I could not initialize the gapi.client, The drive api is enabled. I am new to Javascript, Can anyone please help me download the files using file ids. The File ids are stored in ids[] array in the code.
Thank you for trying to help me out

Google Picker with access token

I'm using Google Picker to get files from Google Drive.
I will be getting my Refresh Token and Access Token from my Database.
My old code which is working fine with User Authentication which asks for username and password for the first time.
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
function onGoogleApiLoad() {
gapi.load('auth', { 'callback': onGoogleAuthApiLoad });
gapi.load('picker');
}
function onGoogleAuthApiLoad() {
window.gapi.auth.authorize({
'client_id': 'MY_CLIENT_ID',
'scope': ['https://www.googleapis.com/auth/drive']
}, handleAuthResult);
}
var oGoogleauthToken;
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
debugger;
oGoogleauthToken = authResult.access_token;
createGooglePicker();
}
}
Now, I'm trying to open the Picker using the Access token by the following code because I don't want to ask for User Authentication any more.
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
var oGoogleauthToken = MY_TOKEN_FROM_DATABASE;
createGooglePicker();
function createGooglePicker() {
debugger;
var picker = new google.picker.PickerBuilder()
.addView(new google.picker.DocsView())
.setOAuthToken(oGoogleauthToken)
.setDeveloperKey('MY_DEVELOPER_KEY')
.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setCallback(GooglepickerCallback)
.build();
picker.setVisible(true);
}
But I'm getting an error like google is not defined.
Is there any way, I can do this?
Is there any thing, I need to do in the script reference file?

Transferring file from Google to Parse.com

I have created a system where user selects files from their Google drive to be uploaded into Parse.
I have done so separately though, where I have one code that allows user to select an item from Google drive, and one that allows user to upload a file from their computer into parse.
Google drive (Using Google drive picker):
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>eSnail Scan Upload Part 2</title>
<script type="text/javascript">
// The Browser API key obtained from the Google Developers Console.
var developerKey = 'KEY';
// The Client ID obtained from the Google Developers Console.
var clientId = 'ID';
// Scope to use to access user's photos.
var scope = ['https://www.googleapis.com/auth/photos'];
var pickerApiLoaded = false;
var oauthToken;
// Use the API Loader script to load google.picker and gapi.auth.
function onApiLoad() {
gapi.load('auth', {'callback': onAuthApiLoad});
gapi.load('picker', {'callback': onPickerApiLoad});
}
function onAuthApiLoad() {
window.gapi.auth.authorize(
{
'client_id': clientId,
'scope': scope,
'immediate': false
},
handleAuthResult);
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
}
// Create and render a Picker object for picking user Photos.
function createPicker() {
if (pickerApiLoaded && oauthToken) {
var picker = new google.picker.PickerBuilder().
enableFeature(google.picker.Feature.MULTISELECT_ENABLED).
addView(google.picker.ViewId.PDFS).
setOAuthToken(oauthToken).
setDeveloperKey(developerKey).
setCallback(pickerCallback).
build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
var url = 'nothing';
if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
var doc = data[google.picker.Response.DOCUMENTS][0];
url = doc[google.picker.Document.URL];
}
var message = 'The following(s) were stored in Parse: ' + url;
document.getElementById('result').innerHTML = message;
}
</script>
</head>
<body>
<div id="result"></div>
<div id="demo">
<!-- The Google API Loader script. -->
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>
</html>
That allows a user to upload a file into Parse (PDF):
<HTML>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script type="text/javascript" src="http://www.parsecdn.com/js/parse-1.2.15.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
// ***************************************************
// NOTE: Replace the following your own keys
// ***************************************************
Parse.initialize("ID", "ID");
function saveDocumentUpload(objParseFile)
{
var documentUpload = new Parse.Object("Scan");
documentUpload.set("Name", "");
documentUpload.set("DocumentName", objParseFile);
documentUpload.save(null,
{
success: function(uploadResult) {
// Execute any logic that should take place after the object is saved.
},
error: function(uploadResult, error) {
// Execute any logic that should take place if the save fails.
// error is a Parse.Error with an error code and description.
alert('Failed to create new object, with error code: ' + error.description);
}
});
}
$('#myForm').bind("submit", function (e) {
e.preventDefault();
var fileUploadControl = $("#documentFileUpload")[0];
var file = fileUploadControl.files[0];
var name = file.name; //This does *NOT* need to be a unique name
var parseFile = new Parse.File(name, file);
var user_id = $('#user_id').val();
var address = $('#address').val();
parseFile.set('UserId', user_id);
parseFile.set('Address', address);
parseFile.save().then(
function () {
saveDocumentUpload(parseFile);
},
function (error) {
alert("error");
}
);
});
});
</script>
<body><form id='myForm'>
<input type="file" id="documentFileUpload">
<br/>
<input type="text" placeholder="UserID" id="user_id">
<br/>
<input type="text" placeholder="Address" id="address">
<br/>
<input type="submit" value="submit">
</form>
</body>
</HTML>

Why am I unable to get the contacts from my phone with Cordova's Contacts API?

I'm building a phone app with Phonegap well, actually with Steroids.js which is built on top of Phonegap. Right now, all I want to do is retrieve the list of contact names and numbers from my phone upon the launching of my app. I took a look at the Contacts api here and I thought I was using it correctly. Below is the script I have inside of my head tags. What have I done wrong?
<script src="http://localhost/cordova.js"></script>
<script src="components/steroids-js/steroids.js"></script>
<script src="javascripts/application.js"></script>
<script type="text/javascript" charset="utf-8">
// Wait for device API libraries to load
//
document.addEventListener("deviceready", onDeviceReady, false);
// device APIs are available
//
function onDeviceReady() {
var options = new ContactFindOptions();
options.filter = "";
var fields = ["displayName", "name"];
navigator.contacts.find(fields, onSuccess, onError, options);
}
function onSuccess(contacts) {
alert('ons');
for (var i = 0; i < contacts.length; i++) {
//trying to display contacts in an alert message when I launch my app
alert("Display Name = " + contacts[i].displayName);
}
}
// onError: Failed to get the contacts
function onError(contactError) {
alert('onError!');
}
</script>
In your above code your cordova.js file is misplaced somewhere.
like
<script src="http://localhost/cordova.js"></script>
You need to copy that cordova.js file into assest/www/ folder (like assest/www/cordova.js)
so it becomes like below in your html file
<script src="cordova.js"></script>

Google Drive Picker - Developer Key is Invalid Error

I started to learn Google Drive Picker API and started with my localhost (I have created my client id and browser key for the domain http://localhost/ and my files locations are localhost/ch1.html etc.
Here's the script I wrote in the body part of my document:
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
<script>
function onApiLoad(){
gapi.load('auth',{'callback':onAuthApiLoad});
gapi.load('picker');
}
function onAuthApiLoad(){
window.gapi.auth.authorize({
'client_id':'545195528713-tihc7u0hp9ihta5mrm4l0eon16fpjogi.apps.googleusercontent.com',
'scope':['https://www.googleapis.com/auth/drive']
},handleAuthResult);
}
var oauthToken;
function handleAuthResult(authResult){
if(authResult && !authResult.error){
oauthToken = authResult.access_token;
createPicker();
}
}
function createPicker(){
var picker = new google.picker.PickerBuilder()
.addView(new google.picker.DocsUploadView())
.addView(new google.picker.DocsView())
.setOAuthToken(oauthToken)
.setDeveloperKey('AIzaSyB3I3JOepScrZgySA9tBWL9pXAUaLJ-NFg')
.build();
picker.setVisible(true);
}
</script>
But when I run the doc it shows nothing. Is it like I can't use the drive api on localhost or I will have to use some button to call it or something like that please help.
Tested Example -
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
<script>
function onApiLoad(){
gapi.load('auth',{'callback':onAuthApiLoad});
gapi.load('picker');
}
function onAuthApiLoad(){
window.gapi.auth.authorize({
'client_id':'545195528713-tihc7u0hp9ihta5mrm4l0eon16fpjogi.apps.googleusercontent.com',
'scope':['https://www.googleapis.com/auth/drive']
},handleAuthResult);
}
var oauthToken;
function handleAuthResult(authResult){
if(authResult && !authResult.error){
oauthToken = authResult.access_token;
createPicker();
}
}
function createPicker(){
var picker = new google.picker.PickerBuilder()
.addView(new google.picker.DocsUploadView())
.addView(new google.picker.DocsView())
.setOAuthToken(oauthToken)
.setDeveloperKey('AIzaSyC4N7lg1vN6YrxcD5DDt_Iu0GXsF3QGFDU')
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
function pickerCallback(data) {
var url = 'nothing';
if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
var doc = data[google.picker.Response.DOCUMENTS][0];
url = doc[google.picker.Document.URL];
}
var message = 'You picked: ' + url;
document.getElementById('result').innerHTML = message;
}
</script>
</head>
<body>
<div id="result"></div>
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>
</html>
You must enable picker api: go https://console.developers.google.com/ select your project then click APIs & auth find Google Picker API and enable it.
I add .setCallback(pickerCallback) to createPicker function and add new function (pickerCallback)
complete code:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
<script>
function onApiLoad(){
gapi.load('auth',{'callback':onAuthApiLoad});
gapi.load('picker');
}
function onAuthApiLoad(){
window.gapi.auth.authorize({
'client_id':'545195528713-tihc7u0hp9ihta5mrm4l0eon16fpjogi.apps.googleusercontent.com',
'scope':['https://www.googleapis.com/auth/drive']
},handleAuthResult);
}
var oauthToken;
function handleAuthResult(authResult){
if(authResult && !authResult.error){
oauthToken = authResult.access_token;
createPicker();
}
}
function createPicker(){
var picker = new google.picker.PickerBuilder()
.addView(new google.picker.DocsUploadView())
.addView(new google.picker.DocsView())
.setOAuthToken(oauthToken)
.setDeveloperKey('AIzaSyB3I3JOepScrZgySA9tBWL9pXAUaLJ-NFg')
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
function pickerCallback(data) {
var url = 'nothing';
if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
var doc = data[google.picker.Response.DOCUMENTS][0];
url = doc[google.picker.Document.URL];
}
var message = 'You picked: ' + url;
document.getElementById('result').innerHTML = message;
}
</script>
</head>
<body>
<div id="result"></div>
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>
</html>
I don't know if Google has changed the API's since the accepted answer, but today, in January 2015, this worked for me, where the above answers didn't:
According to the Credentials page:
Public API access
Use of this key does not require any user action or consent, does not grant access to any account information, and is not used for authorization.
Elsewhere I read that the API/Developer/Browser key is not needed if oAuthToken is used. So, I amended the above code, by simply losing the line:
.setDeveloperKey('AIzaSyB3I3JOepScrZgySA9tBWL9pXAUaLJ-NFg')
For completeness, here's the full amended code, hope it works for you:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
<script>
function onApiLoad() {
gapi.load('auth', { 'callback': onAuthApiLoad });
gapi.load('picker');
}
function onAuthApiLoad() {
window.gapi.auth.authorize({
'client_id': '545195528713-tihc7u0hp9ihta5mrm4l0eon16fpjogi.apps.googleusercontent.com',
'scope': ['https://www.googleapis.com/auth/drive']
}, handleAuthResult);
}
var oauthToken;
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
}
function createPicker() {
var picker = new google.picker.PickerBuilder()
//.addView(new google.picker.DocsUploadView())
.addView(new google.picker.DocsView())
.setOAuthToken(oauthToken)
//.setDeveloperKey('AIzaSyDPs9U-dgOC9h1jRFNwOwhRtARCph8_3HM')
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
function pickerCallback(data) {
var url = 'nothing';
if (data[google.picker.Response.ACTION] == google.picker.Action.PICKED) {
var doc = data[google.picker.Response.DOCUMENTS][0];
url = doc[google.picker.Document.URL];
}
var message = 'You picked: ' + url;
document.getElementById('result').innerHTML = message;
}
</script>
</head>
<body>
<div id="result"></div>
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=onApiLoad"></script>
</body>
</html>
Check that popups aren't being blocked
(there should be a popup allowing you to authorise the client app)
Create and use API key for Browser application instead of API key for Server application as it is done in the images provided by you. That will solve the problem.
Thanks.

Categories

Resources