De Google Drive API - folders
Beschrijving
Een folder op Google Drive is geen folder zoals we die gewoon zijn in bijvoorbeeld Explorer. Op Google drive zitten alle bestanden in één zak. Je kan bepaalde bestanden in die zak groeperen door er een gemeenschappelijke oudertag aan toe te kennen.
Filmpje: De Google Drive API - Folders
Code vind je op mijn team workspace in les 9.
Overzicht bestanden

Een folder creëren
Filmpje: Een folder aanmaken met Google Drive API, voorbeeld van internet halen, aanpassen en debuggen.
Een feedback helper functie
Een algemene functie om feedback aan de ontwikkelaar te geven. Deze methode:
- accepteert een string als argument met de feedback
- creëert een
div
element metid
ingesteld op feedback als dit element niet bestaat - creëert een
p
en eentext
element en voegt dit toe aan het feedback element
/** * Helper function showFeedback * Append a p element to the feedback html element * with the given text as its text node. * * @param {string} text Text to be placed in the p element. */ function showFeedback(text) { var feedback = document.getElementById('feedback'); if (!feedback) { feedback = document.createElement('div'); document.body.appendChild(feedback); } var p = document.createElement('p'); var textContent = document.createTextNode(text); p.appendChild(textContent); feedback.appendChild(p); }
Je kan dat element verbergen door in de css het display
attribuut op none
in te stellen, maar tijdens de ontwikkeling is dat zeer nuttige informatie.
De Google Drive API versie 3 laden
Deze methode roept een callback methode op met de naam makeDriveApiCall
, die zal worden uitgevoerd als de API geladen is.
/** * Load Drive API client library. * Samples: https://advancedweb.hu/2015/05/26/accessing-google-drive-in-javascript/ */ function makeDriveApiCall() { gapi.client.load('drive', 'v3', isUploadFolderPresent); }
Een folder maken
Deze methode maakt een folder in de 'root' van de Google Drive.
/** * Drive API Helper function createFolder * Create a folder with the name given in the title parameter * * @param {string} title the name of the folder to be created */ function createFolder(title) { var body = { 'title': title, 'mimeType': "application/vnd.google-apps.folder" }; var request = gapi.client.request({ 'path': '/drive/v2/files', 'method': 'POST', 'body': body }); request.execute(function(resp) { showFeedback(JSON.stringify(resp, 4)); // console.log('Folder ID: ' + resp.id); }); }
Bestaat de myap
upload folder?
In deze methode gebruiken we de Array.prototype.some()
methode om na te gaan of een bepaald element in de array zit. Let op het q
attribuut waarin we specifiëren dat we alleen folders ophalen die niet gedeleted zijn.
/** * This returns a promise with the result. * One thing we should do is to first check if the folder is present, * and only create it if it is not. * This is a simple listing with filters to the directory mime type * and not trashed (m.a.w. gedeleted door de gebruiker), * then check if there is a result. */ function isUploadFolderPresent() { return gapi.client.drive.files.list({ q: "mimeType = 'application/vnd.google-apps.folder' and trashed = false" }).then(function(files) { showFeedback(JSON.stringify(files, 4)); var folder = files.result.files; showFoldersInExplorer(); if (folder.some(function(item) { return item.name === 'myap' })) {} else { var request = createFolder('myap'); } return 'myap'; }); }
Een nieuwe folder creëren in de myap
folder
We voegen een input element toe waarin de naam van de te maken folder kan worden getypt en een knop die een folder met de ingetypte naam effectief maakt. We voegen een eventlistener toe aan die knop in de methode handleInitialSignInStatus
die op de myaa.html pagina staat:
<script>
/**
* Handle the initial sign-in state.
* This method is called by the OAuth initAuth method and is
* called once the user is signed in succesfully
*/
var handleInitialSignInStatus = function() {
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
signinButton.addEventListener("click", signIn);
signoutButton.addEventListener("click", signOut);
createFolderButton.addEventListener("click", prepareCreateFolder);
makePeopleApiCall();
makeDriveApiCall();
}
</script>
In de callback prepareCreateFolder
methode:
- valideren we de ingetype foldernaam: er moet een naam zijn ingetypt en deze mag alleen letters, cijfers, een underscore, een spatie en een punt bevatten;
- we kijken als de naam van de folder reeds in gebruik is; op Google Drive wordt een bestand of folder geIdentificeerd met een Id en niet met een naam, wat wil zeggen dat je zelf ervoor moet zorgen dat er geen bestanden of folders met dezelfde naam gecreëerd worden; dan doen we met de
Array.prototype.some()
methode. - om een folder te maken in een reeds bestaande folder moeten we de id meegeven van de folder waarin de nieuwe folder moet worden gemaakt; in dit voorbeeld beperken we ons tot de mogelijkheid om een folder in de
myap
map te maken; met de methodeArray.prototype.find()
halen we de id van demyap
folder op; - we roepen in de
then
methode van de API call de methodecreateFolderInParent
op om de folder in demyap
folder te maken;
/** * Prepare the creation of a new folder */ function prepareCreateFolder() { var folderName = document.getElementById('folderName').value; var pathName = 'myap'; if (folderName.length > 0) { var regExpresion = new RegExp("[^a-zA-Z0-9_. ]+"); if (regExpresion.test(folderName)) { alert('Ongeldige foldernaam: ' + folderName) } else { gapi.client.drive.files.list({ q: "mimeType = 'application/vnd.google-apps.folder' and trashed = false" }).then(function(files) { showFeedback(JSON.stringify(files, 4)); var folder = files.result.files; // check is the folder already exists // names not case sensitive if (folder.some(function(item) { return item.name.toLowerCase() === folderName.toLowerCase() })) { alert('Folder met de naam ' + folderName + ' bestaat al!') } else { // fetch folder Id of the root map var folderItem = folder.find(function(item) { return item.name === pathName; }) if (folderItem) { createFolderInParent(folderName, folderItem.id); }; } }); } } else { alert('Typ eerst een naam voor de folder in.'); } }
De createFolderInParent
methode heeft twee parameters, één voor de naam van de te creëren folder en één voor de id van de parent folder. In ons voorbeeld is de id van de myap
folder.
We geven het parents
attribuut mee dat ingesteld is op de id van de myap
folder en nadat de map is gemaakt roepen we de methode showFeedback
en showFoldersInExplorer op :
/** * Drive API Helper function createFolderInParent * Create a folder with the name given in the title parameter * in the root folder (myap) * * @param {string} title the name of the folder to be created */ function createFolderInParent(title, parentId) { var body = { 'title': title, 'mimeType': "application/vnd.google-apps.folder", 'parents': [{ "id": parentId }] }; var request = gapi.client.request({ 'path': '/drive/v2/files', 'method': 'POST', 'body': body }); request.execute(function(resp) { showFeedback(JSON.stringify(resp, 4)); // console.log('Folder ID: ' + resp.id); showFoldersInExplorer(); }); }
De showFoldersInExplorer
methode maakt API call naar Google Drive API om een lijst van de niet gedelete folders op de Google Drive op te halen en te tonen in het HTML element met id="feedback"
:
/** * Show folders in the Explorer */ function showFoldersInExplorer() { var explorer = clearExplorer(); // if no folder info is passed get it from Google Drive API gapi.client.drive.files.list({ q: "mimeType = 'application/vnd.google-apps.folder' and trashed = false" }).then(function(files) { folder = files.result.files; folder.map(function(item) { var p = document.createElement('p'); var textContent = document.createTextNode(item.name); p.appendChild(textContent); explorer.appendChild(p); }); }) }
HTML
<!doctype html> <html lang="nl"> <head> <meta charset="UTF-8"> <title>Google Drive API - Een eerste begin</title> <script> var apiKey = 'AIzaSyAmd2VnWexHajlyARnDykoXQUHyGg24RsM'; var clientId = '420594077145-po45ldmitjnulihvt5309kmeoltb9pmq.apps.googleusercontent.com'; var scopes = ['profile', 'https://www.googleapis.com/auth/drive.file']; </script> <link rel="stylesheet" href="css/myaa.css" type="text/css" /> <script type="text/javascript" src="js/google-oauth-api.js"></script> <script type="text/javascript" src="js/google-people-api.js"></script> <script type="text/javascript" src="js/google-drive-api.js"></script> <script type="text/javascript" src="js/helpers.js"></script> <script> /** * Handle the initial sign-in state. * This method is called by the OAuth initAuth method and is * called once the user is signed in succesfully */ var handleInitialSignInStatus = function() { updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get()); signinButton.addEventListener("click", signIn); signoutButton.addEventListener("click", signOut); createFolderButton.addEventListener("click", prepareCreateFolder); makePeopleApiCall(); makeDriveApiCall(); } </script> </head> <body> <header id=user-profile> <h1>Myaa</h1> <!--Knoppen toevoegen om auth te initialiseren en af te melden --> <button id="signin-button">Aanmelden</button> <button id="signout-button">Afmelden</button> </header> <main> <div id="editor"> <header class="command-panel"></header> <textarea></textarea> </div> <aside id="explorer"> <header class="command-panel"> <label for="folder-name">Foldernaam: </label> <input type="text" placeholder="naam nieuwe map" id="folderName" /> <button type="button" id="createFolderButton">Folder maken</button> </header> <div id="list"></div> </aside> </main> <div id="feedback"> </div> <script> var signinButton = document.getElementById('signin-button'); var signoutButton = document.getElementById('signout-button'); </script> <script src="https://apis.google.com/js/api.js?onload=handleClientLoad"></script> </body> </html>
CSS
Ik heb eenvoudige CSS toegevoegd om het geheel presentabel te maken.
* { box-sizing: border-box; margin: 0; padding: 0; } html { height: 100%; width: 100%; } body { height: 100%; width: 100%; } #user-profile { height: 17%; width: 100%; background-color: #e24510 /* H1 header rood, realgar */ } #user-profile h1 { float: left; } #user-profile img { float: right; } #signin-button, #signout-button { display: none; float: right; } main { height: 83%; width: 100%; } #editor { height: 100%; width: 60%; float: left; background-color: #faebd7 /* Antique white mocassin */ } #editor textarea { width: 100%; height: 90%; background-color: #fff8e7 /* COSMIC LATTE */ } #editor .command-panel { height: 10%; width: 100%; background-color: #010101 /* Lamp black */ } #explorer { height: 100%; width: 40%; float: right; overflow-y: auto; background-color: #faf0e6 /* linnen */ } #explorer ul { margin: 0 1em 0 1em; }
JavaScript
helpers.js
/** * Helper function showFeedback * Append a p element to the feedback html element * with the given text as its text node. * * @param {string} text Text to be placed in the p element. */ function showFeedback(text) { var feedback = document.getElementById('feedback'); if (!feedback) { feedback = document.createElement('div'); document.body.appendChild(feedback); } var p = document.createElement('p'); var textContent = document.createTextNode(text); p.appendChild(textContent); feedback.appendChild(p); }
google-api-people.js
// Load the API and make an API call. Display the results on the screen. function makePeopleApiCall() { gapi.client.load('people', 'v1', getUserProfile); } function getUserProfile() { clearUserProfile(); // Note: In this example, we use the People API to get the current // user's name. In a real app, you would likely get basic profile info // from the GoogleUser object to avoid the extra network round trip. var profile = gapi.auth2.getAuthInstance().currentUser.get().getBasicProfile(); setUserProfile(profile.getGivenName(), profile.getImageUrl()); } function clearUserProfile() { var userProfile = document.getElementById('user-profile'); var h1 = document.querySelector('#user-profile h1'); if (h1) { h1.innerHTML = 'Myaa'; } var img = document.querySelector('#user-profile img'); if (img) { userProfile.removeChild(img); } } function setUserProfile(givenName, imageUrl) { var h1 = document.querySelector('#user-profile h1'); if (h1) { h1.innerHTML = 'Myaa van ' + givenName; } else { h1 = document.createElement('h1'); h1.appendChild(document.createTextNode('Myaa van ' + givenName)); document.getElementById('user-profile').appendChild(h1); } var img = document.createElement('img'); img.setAttribute("src", imageUrl); document.getElementById('user-profile').appendChild(img); }
google-oauth-api.js
function handleClientLoad() { // Load the API client and auth library gapi.load('client:auth2', initAuth); } function initAuth() { // gapi.client.setApiKey(apiKey); gapi.auth2.init({ client_id: clientId, scope: scopes.join(' '), immediate: true }).then(function() { // Listen for sign-in state changes. gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus); }).then(handleInitialSignInStatus); } function updateSigninStatus(isSignedIn) { if (isSignedIn) { signinButton.style.display = 'none'; signoutButton.style.display = 'block'; } else { signinButton.style.display = 'block'; signoutButton.style.display = 'none'; clearUserProfile(); clearExplorer(); } } function signIn(event) { gapi.auth2.getAuthInstance().signIn(); } function signOut(event) { gapi.auth2.getAuthInstance().signOut(); }
google-drive-api.js
/** * Load Drive API client library. * Samples: https://advancedweb.hu/2015/05/26/accessing-google-drive-in-javascript/ */ function makeDriveApiCall() { gapi.client.load('drive', 'v3', isUploadFolderPresent); } /** * This returns a promise with the result. * One thing we should do is to first check if the folder is present, * and only create it if it is not. * This is a simple listing with filters to the directory mime type * and not trashed (m.a.w. gedeleted door de gebruiker), * then check if there is a result. */ function isUploadFolderPresent() { return gapi.client.drive.files.list({ q: "mimeType = 'application/vnd.google-apps.folder' and trashed = false" }).then(function(files) { showFeedback(JSON.stringify(files, 4)); var folder = files.result.files; showFoldersInExplorer(); if (folder.some(function(item) { return item.name === 'myap' })) {} else { var request = createFolder('myap'); } return 'myap'; }); } /** * Drive API Helper function createFolder * Create a folder with the name given in the title parameter * * @param {string} title the name of the folder to be created */ function createFolder(title) { var body = { 'title': title, 'mimeType': "application/vnd.google-apps.folder" }; var request = gapi.client.request({ 'path': '/drive/v2/files', 'method': 'POST', 'body': body }); request.execute(function(resp) { showFeedback(JSON.stringify(resp, 4)); // console.log('Folder ID: ' + resp.id); }); } /** * Drive API Helper function createFolderInParent * Create a folder with the name given in the title parameter * in the root folder (myap) * * @param {string} title the name of the folder to be created */ function createFolderInParent(title, parentId) { var body = { 'title': title, 'mimeType': "application/vnd.google-apps.folder", 'parents': [{ "id": parentId }] }; var request = gapi.client.request({ 'path': '/drive/v2/files', 'method': 'POST', 'body': body }); request.execute(function(resp) { showFeedback(JSON.stringify(resp, 4)); // console.log('Folder ID: ' + resp.id); showFoldersInExplorer(); }); } /** * Prepare the creation of a new folder */ function prepareCreateFolder() { var folderName = document.getElementById('folderName').value; var pathName = 'myap'; if (folderName.length > 0) { var regExpresion = new RegExp("[^a-zA-Z0-9_. ]+"); if (regExpresion.test(folderName)) { alert('Ongeldige foldernaam: ' + folderName) } else { gapi.client.drive.files.list({ q: "mimeType = 'application/vnd.google-apps.folder' and trashed = false" }).then(function(files) { showFeedback(JSON.stringify(files, 4)); var folder = files.result.files; // check is the folder already exists // names not case sensitive if (folder.some(function(item) { return item.name.toLowerCase() === folderName.toLowerCase() })) { alert('Folder met de naam ' + folderName + ' bestaat al!') } else { // fetch folder Id of the root map var folderItem = folder.find(function(item) { return item.name === pathName; }) if (folderItem) { createFolderInParent(folderName, folderItem.id); }; } }); } } else { alert('Typ eerst een naam voor de folder in.'); } } /** * Clear files and folders in the Explorer */ function clearExplorer() { var list = document.querySelector('#list'); list.innerHTML = ''; return list; } /** * Show folders in the Explorer */ function showFoldersInExplorer() { var explorer = clearExplorer(); // if no folder info is passed get it from Google Drive API gapi.client.drive.files.list({ q: "mimeType = 'application/vnd.google-apps.folder' and trashed = false" }).then(function(files) { folder = files.result.files; folder.map(function(item) { var p = document.createElement('p'); var textContent = document.createTextNode(item.name); p.appendChild(textContent); explorer.appendChild(p); }); }) } /** * Show files in the Explorer */ function showFilesInExplorer() { var explorer = clearExplorer(); // if no folder info is passed get it from Google Drive API // id, name, kind and mimeType are the only possible values // you can ommit altogether the fields property gapi.client.drive.files.list({ 'pageSize': 100, 'fields': "nextPageToken, files(id, name, kind, mimeType)" }).then(function(files) { showFeedback(JSON.stringify(files, 4)); folder = files.result.files; folder.map(function(item) { var p = document.createElement('p'); var textContent = document.createTextNode(item.name); p.appendChild(textContent); explorer.appendChild(p); }); }) }