# Google Drive API gebruiken in Python [[TOC]] Google Drive is de centrale opslag van Workspace, en met de Drive API maak je die volledig scriptbaar. Je uploadt rapporten, organiseert mappen, beheert wie wat mag zien en houdt wijzigingen bij. Voor backup-systemen, document-pipelines en integraties is dit een van de meest gebruikte API's. In dit artikel bouw je de kernoperaties op met de Drive API v3 en de officiele `google-api-python-client`. ## De service opzetten Eerst bouw je een service-object met je credentials. Voor servertaken gebruik je doorgaans een service-account met de juiste OAuth-scopes. ```python from googleapiclient.discovery import build service = build("drive", "v3", credentials=credentials) ``` De scope `https://www.googleapis.com/auth/drive.file` geeft toegang tot bestanden die je app zelf aanmaakt of opent. Voor volledige toegang gebruik je `https://www.googleapis.com/auth/drive`, maar vraag altijd de smalst mogelijke scope aan. ## Een bestand uploaden Uploaden combineert metadata met de bestandsinhoud via een MediaFileUpload. ```python from googleapiclient.http import MediaFileUpload metadata = {"name": "rapport.pdf", "parents": [MAP_ID]} media = MediaFileUpload("rapport.pdf", mimetype="application/pdf") bestand = service.files().create( body=metadata, media_body=media, fields="id" ).execute() print(bestand["id"]) ``` :::info title="Waar belandt het bestand?" Het `parents`-veld bepaalt in welke map het bestand komt. Laat je het weg, dan belandt het in de hoofdmap van Drive. Een bestand kan in de nieuwe Drive maar in een enkele map tegelijk staan. ::: Voor grote bestanden zet je `resumable=True`, zodat een onderbroken upload hervat in plaats van opnieuw begint. ```python media = MediaFileUpload("groot-bestand.zip", resumable=True) request = service.files().create(body=metadata, media_body=media, fields="id") respons = None while respons is None: status, respons = request.next_chunk() ``` ## Zoeken met de query-syntax De `q`-parameter is krachtig. Je filtert op naam, type, map, eigenaar en meer. ```python resultaat = service.files().list( q="mimeType='application/pdf' and '" + MAP_ID + "' in parents and trashed=false", fields="files(id, name)" ).execute() for f in resultaat.get("files", []): print(f["name"], f["id"]) ``` :::tip title="Sneller en gerichter zoeken" Combineer voorwaarden met `and` en `or`, en gebruik `trashed=false` om verwijderde bestanden uit te sluiten. Vraag met de `fields`-parameter alleen de velden op die je nodig hebt, dat versnelt grote zoekopdrachten merkbaar. Voor lange resultaten blader je verder met de teruggegeven `nextPageToken`. ::: ## Bestanden delen Toegang regel je via de permissions-resource. Je kent een rol toe aan een gebruiker, groep, domein of iedereen. :::howto title="Toegang verlenen en intrekken" 1. Bepaal wie toegang krijgt en met welke rol (`reader`, `commenter`, `writer`). 2. Roep `permissions().create()` aan met `type` en `emailAddress`. 3. Zet `sendNotificationEmail` op de gewenste waarde. 4. Voor intrekken gebruik je `permissions().delete()` met het permission-ID. ::: ```python permissie = {"type": "user", "role": "writer", "emailAddress": "collega@bedrijf.nl"} service.permissions().create( fileId=BESTAND_ID, body=permissie, sendNotificationEmail=True ).execute() ``` :::danger title="Pas op met openbaar delen" Wees voorzichtig met het type `anyone`, dat maakt een bestand toegankelijk voor iedereen met de link. Voor gevoelige documenten gebruik je altijd type `user` of `group` met expliciete adressen, en audit je periodiek welke bestanden breed gedeeld zijn. ::: ## Downloaden Voor binaire bestanden gebruik je `get_media` en een downloader die in stukken werkt. ```python from googleapiclient.http import MediaIoBaseDownload import io request = service.files().get_media(fileId=BESTAND_ID) buffer = io.BytesIO() downloader = MediaIoBaseDownload(buffer, request) klaar = False while not klaar: status, klaar = downloader.next_chunk() ``` Voor Google-eigen formaten zoals Docs, Sheets en Slides bestaat er geen ruwe bestandsinhoud. Die exporteer je met `files().export_media()` naar een doelformaat, bijvoorbeeld PDF. ```python request = service.files().export_media( fileId=DOC_ID, mimeType="application/pdf" ) ``` ## Wijzigingen volgen Voor synchronisatie volg je de changes-resource. Eerst haal je een startpunt op met `changes().getStartPageToken()`, daarna verwerk je met `changes().list()` alleen wat er sinds dat token veranderd is. Dit werkt vergelijkbaar met de syncToken bij Calendar. ```python token = service.changes().getStartPageToken().execute()["startPageToken"] wijzigingen = service.changes().list(pageToken=token).execute() ``` :::tip title="Werk met gedeelde Drives" Wil je ook gedeelde Drives meenemen, geef dan `supportsAllDrives=True` en `includeItemsFromAllDrives=True` mee in je calls. Zonder deze vlaggen zie je alleen Mijn Drive. ::: ## Veelgestelde vragen :::faq ### Wat is het verschil tussen Mijn Drive en gedeelde Drives? Gedeelde Drives horen bij een team in plaats van een persoon. Geef `supportsAllDrives=True` mee in je calls om ermee te werken, en voor zoekopdrachten ook `includeItemsFromAllDrives=True`. ### Hoe upload ik grote bestanden betrouwbaar? Gebruik resumable uploads door `resumable=True` bij MediaFileUpload te zetten en daarna `next_chunk()` te herhalen. Bij een onderbreking hervat de upload in plaats van opnieuw te beginnen. ### Kan ik een Google Doc programmatisch exporteren naar PDF? Ja, met `files().export_media()` en `mimeType` `application/pdf`. Let op: `export_media()` is voor Google-eigen formaten, voor gewone bestanden gebruik je `get_media()`. ### Hoe vind ik de map-ID? Open de map in de browser, het laatste deel van de URL is de ID. Of zoek ernaar met `files().list()` op naam en `mimeType='application/vnd.google-apps.folder'`. ### Welke OAuth-scope heb ik nodig? Voor bestanden die je app zelf aanmaakt of opent volstaat `drive.file`. Pas wanneer je echt alle bestanden van een gebruiker moet beheren gebruik je de bredere `drive`-scope. Vraag altijd de smalst mogelijke scope aan. ### Waarom krijg ik een 403-fout bij het delen? Meestal ontbreekt de juiste scope, of de service-account is geen lid van de gedeelde Drive. Controleer de scopes en voeg de service-account toe als lid met voldoende rechten. ::: Met de Drive API in Python bouw je betrouwbare document-pipelines, backups en integraties die je opslag volledig automatiseren.