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?
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.
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
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>
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
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.
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.
@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.
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.
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