Vorwort
Meine Webanwendung speichert Daten in
localStorage
. Dies war praktisch, bis ich wollte, dass der Benutzer beim Zugriff auf die Site von verschiedenen Geräten aus dasselbe sieht. Das heißt, Remote-Speicher war erforderlich.
Die Anwendung wird jedoch auf GitHub-Seiten "gehostet" und hat keinen Serverteil. Ich habe beschlossen, keinen Server zu erstellen, sondern die Daten bei einem Dritten zu speichern. Dies bietet erhebliche Vorteile:
- Der Server muss nicht bezahlt werden, er schadet dem Kopf in Bezug auf Stabilität und Verfügbarkeit nicht.
- Weniger Code, weniger Fehler.
- Der Benutzer muss sich nicht in meiner Anwendung registrieren (dies ist für viele ärgerlich).
- Der Datenschutz ist höher und der Benutzer weiß, dass seine Daten an einem Ort gespeichert sind, dem er höchstwahrscheinlich mehr vertraut als mir.
Erstens fiel die Wahl auf
remoteStorage.js . Sie bieten ein offenes Datenaustauschprotokoll, eine hübsche API, die Möglichkeit zur Integration in Google Drive und Dropbox sowie deren Server. Aber dieser Weg stellte sich als Sackgasse heraus (warum - eine separate Geschichte).
Am Ende habe ich mich entschieden, Google Drive direkt und die
Google API Client Library (im Folgenden GAPI) als Bibliothek für den Zugriff darauf zu verwenden.
Leider ist die Google-Dokumentation enttäuschend und die GAPI-Bibliothek sieht unvollendet aus. Außerdem hat sie mehrere Versionen und es ist nicht immer klar, um welche es sich handelt. Daher musste die Lösung für meine Probleme in Teilen aus der Dokumentation, Fragen und Antworten zu StackOverflow und zufälligen Beiträgen im Internet gesammelt werden.
Ich hoffe, dieser Artikel spart Ihnen Zeit, wenn Sie Google Drive in Ihrer Anwendung verwenden.
Vorbereitung
Im Folgenden wird beschrieben, wie Sie Schlüssel für die Arbeit mit der Google-API erhalten. Wenn Sie nicht interessiert sind, fahren Sie direkt mit dem nächsten Teil fort.
Schlüssel empfangenErstellen Sie in der Google Developer Console
ein neues Projekt und geben Sie einen Namen ein.
Klicken Sie in der Systemsteuerung auf "API und Dienste aktivieren" und aktivieren Sie Google Drive.
Gehen Sie als Nächstes zum Abschnitt API und Dienste -> Anmeldeinformationen und klicken Sie auf "Anmeldeinformationen erstellen". Es gibt drei Dinge, die Sie tun müssen:
- Konfigurieren Sie "OAuth Access Request Window". Geben Sie den Namen der Anwendung, Ihre Domain im Abschnitt "Autorisierte Domains" und einen Link zur Hauptseite der Anwendung ein. Andere Felder sind optional.
- Klicken Sie im Abschnitt "Anmeldeinformationen" auf "Anmeldeinformationen erstellen" -> "OAuth-Client-ID". Wählen Sie den Typ "Webanwendung". Fügen Sie im Einstellungsfenster "Zulässige Javascript-Quellen" und "Zulässige Umleitungs-URIs" hinzu:
- Ihre Domain (erforderlich)
http://localhost:8000
(optional, um lokal zu arbeiten).

- Klicken Sie im Abschnitt "Anmeldeinformationen" auf "Anmeldeinformationen erstellen" -> "API-Schlüssel". Geben Sie in den Schlüsseleinstellungen die Einschränkungen an:
- Zulässiger Anwendungstyp -> HTTP-Verweise (Websites)
- Akzeptieren Sie http-Anfragen von den folgenden Verweisquellen (Sites) -> Ihrer Domain und Ihrem lokalen Host (wie in Punkt 2).
- Gültige APIs -> Google Drive API

Der Abschnitt Anmeldeinformationen sollte ungefähr so aussehen:

Hier sind wir fertig. Wir gehen zum Code über.
Initialisierung und Login
Die von Google empfohlene Methode zum Aktivieren von GAPI besteht darin, den folgenden Code in Ihren HTML-Code einzufügen:
<script src="https://apis.google.com/js/api.js" onload="this.onload=function(){}; gapi.load('client:auth2', initClient)" onreadystatechange="if (this.readyState === 'complete') this.onload()"> </script>
Nach dem Laden der Bibliothek wird die
initClient
Funktion aufgerufen, die wir selbst schreiben müssen. Sein typisches Aussehen ist wie folgt:
function initClient() { gapi.client.init({
Zur Datenspeicherung verwenden wir den sogenannten
Application Data Ordner . Seine Vorteile gegenüber einem normalen Ordner:
- Der Benutzer sieht es nicht direkt: Dateien daraus verstopfen seinen persönlichen Bereich nicht und er kann unsere Daten nicht ruinieren.
- Andere Anwendungen sehen es nicht und können es auch nicht verderben.
- Der oben erwähnte Bereich gewährt der Anwendung Zugriff darauf, jedoch keinen Zugriff auf die übrigen Dateien des Benutzers. Das heißt, wir werden eine Person nicht durch Anfragen nach Zugang zu ihren persönlichen Daten abschrecken.
Nach erfolgreicher Initialisierung der Google-API führt die Funktion Folgendes aus:
- Fängt an, Anmelde- / Abmeldeereignisse abzufangen - dies sollte höchstwahrscheinlich immer erfolgen.
- Initialisiert die Anwendung. Dies kann vor dem Laden und Initialisieren von GAPI erfolgen - wie Sie es bevorzugen. Mein Initialisierungsverfahren war etwas anders, wenn Google nicht verfügbar ist. Jemand könnte sagen, dass dies nicht der Fall ist :) Aber erstens können Sie in Zukunft mit Schlüsseln und Zugriffsrechten klug sein. Zweitens ist Google beispielsweise in China verboten.
Das An- und Abmelden erfolgt einfach:
function isGapiLoaded() { return gapi && gapi.auth2 } function logIn() { if (isGapiLoaded()) {
Sie erhalten
onSignIn
im
onSignIn
Handler:
function isLoggedIn() { return isGapiLoaded() && gapi.auth2.getAuthInstance().isSignedIn.get() } function onSignIn() { if (isLoggedIn()) {
Leider ist die Arbeit mit Dateien nicht so offensichtlich.
Versprich Helfer
GAPI gibt keine normalen Versprechen zurück. Stattdessen wird eine eigene Thennable-Schnittstelle verwendet, die Versprechungen ähnelt, aber nicht ganz. Aus praktischen
async/await
(hauptsächlich zur Verwendung von
async/await
) werden wir daher einen kleinen Helfer erstellen:
function prom(gapiCall, argObj) { return new Promise((resolve, reject) => { gapiCall(argObj).then(resp => { if (resp && (resp.status < 200 || resp.status > 299)) { console.log('GAPI call returned bad status', resp) reject(resp) } else { resolve(resp) } }, err => { console.log('GAPI call failed', err) reject(err) }) }) }
Diese Funktion verwendet die GAPI-Methode und die Parameter als erstes Argument und gibt Promise zurück. Dann werden Sie sehen, wie man es benutzt.
Mit Dateien arbeiten
Sie sollten immer daran denken, dass
der Dateiname in Google Drive nicht eindeutig ist . Sie können beliebig viele Dateien und Ordner mit demselben Namen erstellen. Nur die Kennung ist eindeutig.
Für grundlegende Aufgaben müssen Sie nicht mit Ordnern arbeiten, daher funktionieren alle folgenden Funktionen mit Dateien im Stammverzeichnis des Ordners Anwendungsdaten. Die Kommentare geben an, was geändert werden muss, um mit Ordnern zu arbeiten. Die Dokumentation von Google finden Sie hier .
Erstellen Sie eine leere Datei
async function createEmptyFile(name, mimeType) { const resp = await prom(gapi.client.drive.files.create, { resource: { name: name,
Diese asynchrone Funktion erstellt eine leere Datei und gibt ihren Bezeichner (String) zurück. Wenn eine solche Datei bereits vorhanden ist, wird eine neue Datei mit demselben Namen erstellt und ihre ID zurückgegeben. Wenn Sie dies nicht möchten, müssen Sie zunächst überprüfen, ob keine Datei mit demselben Namen vorhanden ist (siehe unten).
Google Drive ist keine vollständige Datenbank. Wenn Sie beispielsweise möchten, dass mehrere Nutzer gleichzeitig von verschiedenen Geräten aus mit demselben Google-Konto arbeiten, kann es aufgrund fehlender Transaktionen zu Problemen bei der Lösung von Konflikten kommen. Für solche Aufgaben ist es besser, Google Drive nicht zu verwenden.
Arbeiten Sie mit Dateiinhalten
GAPI (für browserbasiertes JavaScript) bietet keine Methoden zum Arbeiten mit dem Inhalt von Dateien (sehr seltsam, nicht wahr?). Stattdessen gibt es eine allgemeine
request
(einen Thin Wrapper über eine einfache AJAX-Anforderung).
Durch Versuch und Irrtum bin ich zu folgenden Implementierungen gekommen:
async function upload(fileId, content) {
Dateisuche
async function find(query) { let ret = [] let token do { const resp = await prom(gapi.client.drive.files.list, {
Wenn Sie keine
query
angeben, gibt diese Funktion alle Dateien im Anwendungsordner (ein Array von Objekten mit
id
und Namensfeldern) sortiert nach Erstellungszeit zurück.
Wenn Sie die
query
angeben (die Syntax wird
hier beschrieben), werden nur Dateien zurückgegeben, die der Abfrage entsprechen. Um beispielsweise zu überprüfen, ob eine Datei mit dem Namen
config.json
, müssen Sie dies tun
if ((await find('name = "config.json"')).length > 0) {
Dateien löschen
async function deleteFile(fileId) { try { await prom(gapi.client.drive.files.delete, { fileId: fileId }) return true } catch (err) { if (err.status === 404) { return false } throw err } }
Diese Funktion löscht die Datei nach ID und gibt
true
zurück
true
wenn sie erfolgreich gelöscht wurde, und
false
wenn keine solche Datei vorhanden war.
Synchronisieren
Es wird empfohlen, dass das Programm hauptsächlich mit
localStorage
arbeitet und Google Drive nur zum Synchronisieren von Daten aus
localStorage
.
Das Folgende ist eine einfache Konfigurationssynchronisationsstrategie:
- Die neue Konfiguration wird mit einem Login von Google Drive heruntergeladen und anschließend alle 3 Minuten die lokale Kopie überschrieben.
- Lokale Änderungen werden auf Google Drive übertragen und überschreiben, was dort vorhanden war.
- Die Konfigurationsdatei-
fileID
wird in localStorage
zwischengespeichert, um die Arbeit zu beschleunigen und die Anzahl der Anforderungen zu verringern. - Richtig gehandhabte (fehlerhafte) Situationen sind, wenn Google Drive über mehrere Konfigurationsdateien verfügt und jemand unsere Konfigurationsdatei gelöscht oder ruiniert hat.
- Synchronisierungsdetails wirken sich nicht auf den Rest des Anwendungscodes aus. Um mit der Konfiguration zu arbeiten, verwenden Sie nur zwei Funktionen:
getConfig()
und saveConfig(newConfig)
.
In einer realen Anwendung möchten Sie wahrscheinlich eine flexiblere Konfliktbehandlung beim Laden / Entladen einer Konfiguration implementieren.
Fazit
Meiner Meinung nach eignet sich der Datenspeicher für eine Website in Google Drive hervorragend für kleine Projekte und Prototypen. Es ist nicht nur einfach zu implementieren und zu unterstützen, sondern trägt auch dazu bei, die Anzahl unnötiger Entitäten im Universum zu reduzieren. Ich hoffe, mein Artikel hilft Ihnen, Zeit zu sparen, wenn Sie diesen Weg wählen.
PS Der Code des realen Projekts
liegt auf GitHub .
Sie können ihn
hier ausprobieren.