Upload File to Google Drive Using Lightning Component

We have covered many points in lightning, but integration is the one we never touch. So today we will do Integration with google drive and upload file.

First we need to create oAuth app in google developer console https://console.developers.google.com/     

Now after the connect app is created. You will get the Client ID , Client secret. Store them for future reference. You can update the callback URL once we create tab for our component.

Next we need to create Remote Site setting.

After that Just add the below code in your org.

oAuthGDrive.cmp

<aura:component controller="GoogleDriveController" implements="lightning:isUrlAddressable,force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
  	<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <aura:attribute name="accessToken" type="String" />
    <aura:attribute name="myRecordId" type="String" default="0016F0000XXXXXXXXX" description="This is the record where we will temproary store the file"/>
    
    <lightning:card title="Google Drive Demo">
    	<lightning:button variant="brand" label="Google Drive Auth" title="Google Drive Auth" onclick="{! c.doAuth }" />
        <hr/>
        <p class="slds-p-horizontal_small">
            <!--file upload part -->
            <lightning:fileUpload label="upload file to Drive" name="fileUploader"
				multiple="false" accept=".jpg, .png" recordId="{!v.myRecordId}" onuploadfinished="{!c.handleFilesChange}" />
          </p>
    </lightning:card>
</aura:component>

oAuthGDriveController.js

({
	doInit : function(component, event, helper) {
        if(component.get("v.pageReference") != undefined && component.get("v.pageReference") != 'undefined') {
        var code = component.get("v.pageReference").state.code;
        if(code != undefined) {
            var action  = component.get("c.getAccessToken");
            action.setParams({
                "code" : code
            });
        	action.setCallback(this, function(response){
            var status = response.getState();
            if(status === "SUCCESS"){
                var accessToken = response.getReturnValue();
                component.set("v.accessToken", accessToken);
            }
        });
        
        $A.enqueueAction(action);
        }
      }
    },
    
    doAuth : function(component, event, helper) {

	var action  = component.get("c.createAuthURL");
        action.setCallback(this, function(response){
            var status = response.getState();
            if(status === "SUCCESS"){
                var authUrl = response.getReturnValue();
                window.location.href = response.getReturnValue();
				//if you want to use standard method use below code. But it will open in new tab.
               /* var urlEvent = $A.get("e.force:navigateToURL");
                urlEvent.setParams({
                  "url": authUrl
                });
                urlEvent.fire();*/
                
            }
        });
        
        $A.enqueueAction(action);
    },
    
    handleFilesChange : function(component, event, helper) {
        var uploadedFiles = event.getParam("files");
        var attachmentId = uploadedFiles[0].documentId;
        var code = component.get("v.accessToken");
        
        var action  = component.get("c.uploadFile");
        action.setParams({
            "attachmentId": attachmentId,
            "accessToken" : code
        });
        action.setCallback(this, function(response){
            var status = response.getState();
            if(status === "SUCCESS"){
                var responseCode = response.getReturnValue();
                if(responseCode == '200')
                    alert('File Uploaded successfully');
                else
                    alert('There was some error');
            }
        });
        
        $A.enqueueAction(action);
    }
})

GoogleDriveController.apxc

public class GoogleDriveController
{
    private static String key = 'XXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com';
    private Static String secert = 'XXXXXXXXXXXXXXXXXXXXXXX';
    private Static string redirect_uri = 'https://XXXXXXXXXXXXXXXXXXXXXXXX/lightning/n/GDrive_Demo';
    
    @AuraEnabled
    public static String createAuthURL() {
        String key = EncodingUtil.urlEncode(key,'UTF-8');
        String uri = EncodingUtil.urlEncode(redirect_uri,'UTF-8');
        String authuri = '';
        authuri = 'https://accounts.google.com/o/oauth2/auth?'+
        'client_id='+key+
        '&response_type=code'+
        '&scope=https://www.googleapis.com/auth/drive'+
        '&redirect_uri='+uri+
        '&access_type=offline';
        return authuri;
    }
    
    @AuraEnabled
    public static String getAccessToken(String code)
    {
        //Getting access token from google
        HttpRequest req = new HttpRequest();
        req.setMethod('POST');
        req.setEndpoint('https://accounts.google.com/o/oauth2/token');
        req.setHeader('content-type', 'application/x-www-form-urlencoded');
        String messageBody = 'code='+code+'&client_id='+key+'&client_secret='+secert+'&redirect_uri='+redirect_uri+'&grant_type=authorization_code';
        req.setHeader('Content-length', String.valueOf(messageBody.length()));
        req.setBody(messageBody);
        req.setTimeout(60*1000);

        Http h = new Http();
        String resp;
        HttpResponse res = h.send(req);
        resp = res.getBody();
         Map<String,object> responseMap =(Map<String,object>)JSON.deserializeUntyped(res.getBody()) ;  
          String token =  String.valueOf(responseMap.get('access_token'));
         return token;

   }
    
    @AuraEnabled
    public static String uploadFile(String attachmentId, String accessToken) {
        List<ContentVersion> cvFile = [SELECT VersionData,FileType,ContentDocumentId FROM ContentVersion WHERE ContentDocumentId =: attachmentId];
        Blob myBlob = cvFile[0].VersionData;
       String url = 'https://www.googleapis.com/upload/drive/v2/files?uploadType=media';
       string authorizationHeader = 'Bearer ' + accessToken; 
       Integer contentSize = myBlob.size();
       HttpRequest req = new HttpRequest();
       req.setheader('Authorization',authorizationHeader);
       req.setheader('Content-Length',String.valueOf(contentSize));
        req.setheader('Content-Type','image/'+cvFile[0].FileType);
       req.setMethod('POST'); 
       req.setEndpoint(url); 
       req.setBodyAsBlob(myBlob); 
       Http h = new Http(); 
      
       Httpresponse resp = h.send(req);
	   //After file was successfully upload we delete the file
       delete new ContentDocument(Id = cvFile[0].ContentDocumentId);
       return String.valueOf(resp.getStatuscode());
    }
	
}	

Here we are using lightning:fileUpload to upload file on google drive. This is how our final outcome will look.

Do you like the post or want to add anything. Let me know in comments section.

Happy programming 🙂

Advertisements

17 thoughts on “Upload File to Google Drive Using Lightning Component

  1. it’s not working sir ( component.get(“v.pageReference”).state.code; )
    Error : [Cannot read property ‘state’ of undefined]

  2. Same error, and I have lighting:isUrlAddressable, what would be the error? I used the same code that you mention and I obtain the error: Action failed: c:Upload_GDrive$controller$doInit [Cannot read property ‘state’ of null], when I tried to use the lightning component on a page

    1. Yep…me too. And in addiion when I just removed that check and just authenticate each time, the file transfer did not work either. Failed each time.

    2. Thanks for mentioning you are using it in lightning page. Just add this check in init method if(component.get(“v.pageReference”) != undefined && component.get(“v.pageReference”) != ‘undefined’). I have added same in code as well.

  3. if(component.get(“v.pageReference”) != undefined && component.get(“v.pageReference”) != ‘undefined’) Not working

  4. Hi, is there any up-date to this? Tried to add the line what you mentioned in comments but still not working. I´d really appreciate that 🙂

        1. We are using “pageReference” to get attribute from URL. But it is not supported in flexipages so you need to use another way to get URL from parameter. You need to update Init method for this.

  5. Hello, I still have error when tried to load file, it just at the 100% gives an error with Cant upload your file.
    Is there any solution? When I go on Google Drive Auth button, its just redirects me to google with error No_Oauth_State: State was not sent back

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.