De Google Drive API - folders
Home

De Google Drive API - folders

De Google Drive API - folders

De Google Drive API laat ons toe nieuwe mappen op de Google Drive aan te maken.

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

Google Drive API folders voorbeeld
Google Drive API folders voorbeeld

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:

/**
 * 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:

/**
 * 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);
        });
    })
}

JI
2016-10-14 16:46:33