Assistance needed to work with Google Drive API

I’ve hit a bit of a wall with a project which requires a logged in user to upload files and they go into the site owner’s Google Drive, ideally in a folder named with the ID of the user who uploaded it. That’s all I need to do. I don’t need to be able to download anything, browse it, delete, etc. Simply upload. The files will then only be accessed via the normal Google Drive service.

It looks like I should be able to set up the Google Drive API and use OAuth2 and Wappler seems to be able to do all of this but I can’t get my head around it.

Are there any Wappler users who can assist and we’ll pay for your time?

Have a look at - Google OAuth & Photos API Tutorial - Part One: Getting Credentials from Google . That series goes through the whole Oauth procedure.

I’ll have a look and see if I can figure out the Google Drive API. No promises. :slight_smile:

1 Like

Wow, how did I not find your tutorial before? Thanks @Heather_Mann. I will go through it all and see how it goes. If you’re able to successfully upload to a Google Drive in the meantime then that would be fantastic but on first glance, your tutorial looks brilliant.

Huge thanks for all the time you’ve spent on that. I’ll let you know how I get on.

1 Like

Note - depending on whether Drive is client or server side it might get messed up in March by this change - Update Google OAuth for new sign in method (old method deprecated from March 2023)

I’ll have a look over the weekend.

1 Like

Hey Jon - I’ve managed to get a simple file upload working!!! If you’ve followed the first part of that tutorial you should have a client id. You’ll need to replace YOUR-CLIENT-ID-HERE below with that

Also, make sure that you’ve enabled Google Drive at https://console.cloud.google.com/marketplace/product/google/drive.googleapis.com

Hopefully this will work for you. It should take any kind of file. I tried several and they all worked fine. Oh - if you want to put them into a specific folder you can get the folder id from the url of the folder and replace ‘root’ below.

LMK how you go. And if you get it all pretty and working with error handling and all that good stuff I’d love the code. Thx.

<html>

<head>

    <script src="dmxAppConnect/dmxAppConnect.js"></script>

    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>

</head>

<body is="dmx-app" id="Drive">

        <h1>Google Drive using Google Identity Services</h1>

        <input id="inputUpload" type="file">

        <button onclick="getToken();">Get access token</button> <br><br>

        <button onclick="uploadFile();">Upload File</button> <br><br>

        <button onclick="revokeToken();">Revoke token</button>

        <div id="content"></div>

    

    <script>

    //Authorization

      var client;

      var access_token;

      function initClient() {

        client = google.accounts.oauth2.initTokenClient({

          client_id: 'YOUR-CLIENT-ID-HERE',

          scope: 'https://www.googleapis.com/auth/drive.file',

          callback: (tokenResponse) => {

            access_token = tokenResponse.access_token;

          },

        });

      }

      function getToken() {

        client.requestAccessToken();

      }

      function revokeToken() {

        google.accounts.oauth2.revoke(access_token, () => {console.log('access token revoked')});

      }

    //file upload

    async function uploadFile() {

        const fileToUpload = inputUpload.files[0];


        var metadata = {

        name: fileToUpload.name,

        mimeType: fileToUpload.type,

            'parents': ['root'], // Folder ID at Google Drive which is optional

        };

        var accessToken = access_token; 

        var form = new FormData();

        form.append('metadata', new Blob([JSON.stringify(metadata)], { type: 'application/json' }));

        form.append('file', fileToUpload);

        var xhr = new XMLHttpRequest();

            xhr.open('post', 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id');

            xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);

            xhr.responseType = 'json';

            xhr.onload = () => {

            document.getElementById('content').innerHTML = "File uploaded successfully. The Google Drive file id is <b>" + xhr.response.id + "</b>";

            document.getElementById('content').style.display = 'block';

        };

        xhr.send(form);

    }

    </script>

    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>

</body>

</html>
1 Like

Fantastic. Thanks @Heather_Mann. I’ll work through it and let you know.

One further quick question… you mentioned if I want to upload to a particular folder. My plan is to dynamically create a folder named after the ID of the record which the upload is linked to. Would that be possible?

eg. If someone is uploading 5 files as part of submitting a form where the record ID is 123, I want to upload them to /myappname/ID/ so each file would be like MyWebApp/123/document.pdf

What do you think?

Sorry. Just want to check. Is this purely client-side? Nothing in Server Connect? I will be replacing the uploading to the web server with uploading to Google Drive but I still need to do all the other Server Connect stuff like database inserts and updates.

I fear I’m not fully understanding!

You can do the upload to Drive client side but do all your other database stuff server side with Wappler.

So, say for instance you want to add the file id returned from google to your database via a server connect you could do something along the lines of…

xhr.onload = () => {
dmx.parse(“your_servers_connect.load({file_id: " + xhr.response.id +”})";
}

1 Like

You’ve given me a wealth of information which I will go through ASAP. I’ll let you know how I get on. It’s my birthday tomorrow so won’t be working but I plan to be on this early next week.

Huge thanks for your help. I’ll keep you posted.

Here’s the folder code. You could call this and then pass the folderId to the uploadFile function for the parent

function createFolder() {

        var metadata = {

            name: "YOUR_FOLDER_NAME_HERE",

            mimeType: 'application/vnd.google-apps.folder',

            parents: 'root'

        };

        var form = new FormData();

        form.append('metadata', new Blob([JSON.stringify(metadata)], {type: 'application/json'}));

        var xhr = new XMLHttpRequest();

        xhr.open('POST', 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart');

        xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);

        xhr.responseType = 'json';

        xhr.onload = () => {

            var folderId = xhr.response;

            console.log(folderId);

         };

        xhr.send(form);

    }
1 Like

@sitestreet Hi!
Can you please clarify. When users upload files, it would be on behalf of the site owner’s account?

If so, I believe the best way is to use the “Service Account” approach.
https://cloud.google.com/iam/docs/service-accounts

So the users of your project won’t need any google auth for themselves at all. You only set the google auth once for the service account in the Server Actions.

I am successfully using this option in my projects.
I have followed this guide ( Of course, it is a bit outdated in terms of Wappler’s UI.)

But as I recall I had no issues with setting this up. I just followed instructions.
If there will be any questions, feel free to reach out.

Hi Nick

Yes, your question is spot on. All the uploads will be going into the site owner’s account, NOT the user’s account. So the users won’t need any Google credentials at all. And I specifically want the connection to the site owner’s Google Drive to be ‘write only’ so there are no security implications. Once something is uploaded, the only way to access the files is through Google’s own Drive system so even if someone were to gain access to the server or code, they still couldn’t get access to the uploaded files.

Thanks for the tip. I shall go through the link you posted and add that to my training. I’ll be sure to reach out to you if I have any questions so thanks for the offer :slight_smile:

Cheers

Jon

Ah - sorry, my bad. I read the initial question wrong. I guess if anyone needs client side going forward the solution is here. :woman_shrugging:

1 Like