Monday, February 17, 2014

How to upload, update and save an image file to Google Drive using Javascript

This is a simple Javascript Google Drive example web app to load an image file from a local drive, write some text on the image, then save the edited image to Google Drive in the cloud. The basis of this example came from the Google Drive SDK Javascript Quickstart at this location https://developers.google.com/drive/quickstart-js. Read up the Google Drive SDK Javascript Quickstart to see how to enable the Google Drive API and setup a Google Drive Javascript web app.

Setup the Javascript app
Copy the following source code and save into your own html file. Change the string <YOUR_CLIENT_ID> to your own client ID assigned to you when you created your cloud project in http://cloud.google.com/console. Publish the page to a web server.

In general, this is what the Javascript code is doing: (1) load and draw the local image file in the canvas element, (2) draw the string "Hello World" onto the canvas, (3) save the canvas into an IMG element, (4) upload the IMG element source data into Google Drive.

<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<script type="text/javascript">
 
var CLIENT_ID = '<YOUR_CLIENT_ID>';
var SCOPES = 'https://www.googleapis.com/auth/drive';
 
/**
       * Called when the client library is loaded to start the auth flow.
       */
function handleClientLoad() {
window.setTimeout(checkAuth, 1);
}
 
/**
       * Check if the current user has authorized the application.
       */
function checkAuth() {
gapi.auth.authorize(
{'client_id': CLIENT_ID, 'scope': SCOPES, 'immediate': true},
handleAuthResult);
}
 
/**
       * Called when authorization server replies.
       *
       * @param {Object} authResult Authorization result.
       */
function handleAuthResult(authResult) {
var authButton = document.getElementById('authorizeButton');
var filePicker = document.getElementById('filePicker');
var uploadButton = document.getElementById('uploadButton');

authButton.style.display = 'none';
filePicker.style.display = 'none';
uploadButton.style.display = 'none';
if (authResult && !authResult.error) {
// Access token has been successfully retrieved, requests can be sent to the API.
filePicker.style.display = 'block';
filePicker.onchange = loadImageFile;
uploadButton.onclick = newUploadFile;
} else {
// No access token could be retrieved, show the button to start the authorization flow.
authButton.style.display = 'block';
authButton.onclick = function() {
gapi.auth.authorize(
{'client_id': CLIENT_ID, 'scope': SCOPES, 'immediate': false},
handleAuthResult);
};
}
}
 
function newUploadFile(evt){
gapi.client.load('drive','v2', function(){
var theImage = document.getElementById('editedImage');
var fileTitle = theImage.getAttribute('fileName');
var mimeType = theImage.getAttribute('mimeType');
var metadata = {
'title': fileTitle,
'mimeType': mimeType
};
var pattern = 'data:' + mimeType + ';base64,';
var base64Data = theImage.src.replace(pattern,'');            
newInsertFile(base64Data,metadata);
});
}
/**
       * Insert new file.
       *
       * @param {Image} Base 64 image data
       * @param {Metadata} Image metadata
       * @param {Function} callback Function to call when the request is complete.
       */
function newInsertFile(base64Data, metadata, callback){
const boundary = '-------314159265358979323846';
const delimiter = "\r\n--" + boundary + "\r\n";
const close_delim = "\r\n--" + boundary + "--";
var contentType = metadata.mimeType || 'application/octet-stream';
var multipartRequestBody =
delimiter +
'Content-Type: application/json\r\n\r\n' +
JSON.stringify(metadata) +
delimiter +
'Content-Type: ' + contentType + '\r\n' +
'Content-Transfer-Encoding: base64\r\n' +
'\r\n' +
base64Data +
close_delim;
 
var request = gapi.client.request({
'path' : '/upload/drive/v2/files',
'method' : 'POST',
'params' : {
'uploadType' : 'multipart'
},
'headers' : {
'Content-Type' : 'multipart/mixed; boundary="' + boundary + '"'
},
'body' : multipartRequestBody
});
if (!callback) {
callback = function (file) {
alert('done');
};
}
request.execute(callback);
}
function loadImageFile(evt){
var file = evt.target.files[0];
var reader = new FileReader();
reader.file = file;
reader.onload = onImageReaderLoad;
reader.readAsDataURL(file);            
}
function onImageReaderLoad(evt){
var file = this.file;
var mimeType = file.type;
writeSomeText(file.name,file.type,evt.target.result);        
}
/**
       * Write some Hello World text on an image using the canvas.
       *
       * @param {File Name} The name of the image file
       * @param {MimeType} The mime type of the image e.g. image/png
       * @param {Image} The image data
       */
function writeSomeText(sourceImageName, mimeType, sourceImage){
var resultsDiv = document.getElementById('resultsDiv');
var sourceImg = document.createElement('img');
var resultImg = document.createElement('img');
var canvas = document.createElement('canvas');
sourceImg.onload = function(evt){
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(this,0,0,canvas.width,canvas.height);
ctx.font = '24px Arial';
ctx.fillText('Hello World',this.width/2,this.height/2);
ctx.restore();
resultImg.onload = function(evt2){
resultImg.setAttribute('id','editedImage');
resultImg.setAttribute('mimeType', mimeType);
resultImg.setAttribute('fileName', sourceImageName);
resultsDiv.appendChild(resultImg);
var uploadButton = document.getElementById('uploadButton');
uploadButton.style.display = 'block';
};
resultImg.src = canvas.toDataURL(mimeType);
};
sourceImg.src = sourceImage;
}    
 
</script>
<script type="text/javascript" src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>
</head>
<body>
<!--Add a file picker for the user to choose an image file to be edited -->
<input type="file" id="filePicker" style="display: none" />
<!-- Add a button to start the upload process for loading the edited image file to Google Drive -->
<input type="button" id="uploadButton" style="display:none" value="Upload" />
<input type="button" id="authorizeButton" style="display: none" value="Authorize" />
<!-- div placeholder for displaying the edited image -->
<div id="resultsDiv">
</div>
</body>
</html>


Run the Javascript app

  1. Load the web page in an Internet browser.

    If the Javascript app has not been authorized by you, then the Authorize button will be displayed.
  2. Click Authorize.

    If you are not signed in to your Google account, the following page may display. Just type in your password and sign in.


    The Request for permission page appears.
  3. Click Accept.

    The app is authorized and the browser runs the Javascript app.
  4. Click Choose File.

    The Open dialog box appears.
  5. Browse and select an image file, e.g. ic_launcher.png. Click Open.

    The app writes the text string 'Hello World' in the middle of the selected image. The Upload button appears.

  6. Click the Upload button.

    A done message appears.

     The image is saved into your Google Drive in the cloud.
 

2 comments:

bg said...

it works good. used it to upload jsPDF created pdf without saving it to HDD. Thank you.

Ajay Chauhan said...

thank you. now, i want to upload file in specific folder in google drive. is it possible ???