Kategorien
Programmierung

FileSystem-API: Dateien erstellen und lokal speichern mit JavaScript und Webkit

Mit der FileSystem-API ist es möglich, per JavaScript Dateien und Verzeichnisse zu erstellen und diese lokal auf dem Rechner des Nutzers zu speichern. Es kann sich dabei um einfache Text-, aber zum Beispiel auch um Bilddateien handeln. Moderne Webkit-Browser, die HTML5 unterstützen, können mittlerweile auch mit der FileSystem-API umgehen.

html5_filesystem

Zugriff auf lokales Dateisystem

Um Verzeichnisse und Dateien lokal speichern zu können, bedarf es freilich des Zugriffs auf das lokale Dateisystem des Nutzers. Dies ist aus guten Gründen nicht erlaubt, da es ein enormes Sicherheitsrisiko bedeutet. Daher erlaubt die FileSystem-API auch nur den Zugriff auf einen speziellen geschützten Bereich, der vom Browser zur Verfügung gestellt wird. Die API hat nur innerhalb dieses Bereiches Lese- und Schreibzugriff auf Dateien und Verzeichnisse. Es ist also nicht möglich, auf beliebige Verzeichnisse und Dateien eines Rechners zuzugreifen.

Diese Firmen suchen nach Mitarbeitern (via jobs.drweb.de)

Die FileSystem-API unterscheidet zwischen zwei unterschiedlichen Möglichkeiten, Dateien lokal zu speichern. Neben der Möglichkeit, Dateien temporär abzulegen, können sie auch dauerhaft gespeichert werden. Das dauerhafte Ablegen von Dateien erfordert jedoch die explizite Genehmigung des Nutzers. Diese Genehmigung holt sich der Browser über ein Dialogfenster. Um Dateien speichern zu können, muss zunächst der Zugriff auf das Dateisystem eingerichtet werden.

window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, dateispeichern);
window.webkitRequestFileSystem(window.PERSISTENT , 1024*1024, dateispeichern);

Über „webkitRequestFileSystem()“ wird die Speicherart („window.TEMPORARY“ für den vorübergehenden und „window.PERSISTENT“ für den dauerhaften Speicher), das Speicherkontingent (im Beispiel ein Megabyte) sowie eine Funktion, die später Zugriff auf das lokale Dateisystem hat, festgelegt. Derzeit funktioniert die FileSystem-API nur bei Webkit-Browsern mit entsprechendem Vendor-Präfix. Zusätzlich gibt es noch die Möglichkeit, eine Fallback-Funktion als vierten Parameter von „webkitRequestFileSystem()“ zu übergeben. Diese wird ausgeführt, wenn das Freigeben des Speicherkontingents nicht erfolgreich war.

Während temporär gespeicherte Dateien vom Browser bei Bedarf gelöscht werden können (zum Beispiel, weil der Speicherplatz erschöpft ist), bleiben dauerhaft gespeicherte Dateien solange erhalten, bis die Website oder der Nutzer sie explizit löscht. Chrome stellt maximal 50 Prozent der freien Festplattenkapazität für temporäre Kontingente zur Verfügung, wobei jede Website maximal 20 Prozent davon in Anspruch nehmen darf.

Da dauerhafter Speicher nur nach der expliziten Genehmigung des Nutzers eingerichtet wird, ist es erforderlich, den Aufruf von „webkitRequestFileSystem()“ innerhalb eines anderen Aufrufs zu starten, der die Nutzergenehmigung einholt.

navigator.webkitPersistentStorage.requestQuota(1024*1024, function() {
  window.webkitRequestFileSystem(window.PERSISTENT , 1024*1024, dateispeichern);
})

Im Beispiel wird über „webkitPersistentStorage.requestQuota()“ zunächst der Nutzer aufgefordert, das dauerhafte Speichern von Dateien zu erlauben. Erst danach kann per „webkitRequestFileSystem()“ das Speicherkontingent eingerichtet werden.

filesystem_genehmigung
Genehmigungsdialog im Chrome
Die FileSystem-API folgt der „Same Origin Policy“. Das heißt, der Zugriff auf Dateien, die lokal abgespeichert werden, ist nur von der Domain möglich, über welche die Dateien auch abgelegt wurden. So wird verhindert, dass Dateien von anderen Websites abgegriffen werden können.

Dateien erstellen und füllen

Über die Funktion „dateispeichern()“ hat man nun Zugriff auf das freigegebene Speicherkontingent und kann Dateien und Verzeichnisse erstellen und mit Inhalt füllen. Über die Methode „getFile()“ wird auf Dateien zugegriffen. Ist eine Datei nicht vorhanden, kann sie über die Methode erstellt werden.

function dateispeichern(dateisystem) {
  dateisystem.root.getFile("info.txt", {create: true});
}

Der Funktion „dateispeichern()“ wird ein Parameter übergeben, der den Zugriff auf das Dateisystem regelt. Im Beispiel ist er „dateisystem“ genannt. Über „dateisystem.root.getFile()“ wird auf das Wurzelverzeichnis des Dateisystems zugegriffen – und zwar auf die Datei „info.txt“. Neben des Dateinamens wird über „getFile()“ ein sogenanntes Objektliteral übergeben. Dieses enhtält eines oder mehrere Werte, die der Methode mitteilen, was zu tun ist. Der Wert „create: true“ signalisiert der Methode, dass die Datei erzeugt werden soll. Bei „create: false“ wird die Datei, falls sie existiert, aufgerufen.

Um Dateien mit Inhalt zu füllen, gibt es die Methode „createWriter()“. Sie schreibt den Inhalt eines sogenannten Blobs in die Datei. Ein Blob („Binary Large Object“) ist ein binäres Objekt, welches beliebige Inhalte wie Text und Bilder beinhalten kann.

function dateispeichern(dateisystem) {
  dateisystem.root.getFile("info.txt", {create: true}, function(datei) {
    datei.createWriter(function(inhalt) {
      var blob = new Blob(["Lorem Ipsum"], {type: "text/plain"});
      inhalt.write(blob);
    });
  });
}

Um in eine Datei zu schreiben, wird der Methode „getFile()“ als dritter Parameter ein Funktionsaufruf zugewiesen. Dieser Funktion wird der Parameter „datei“ übergeben. Darüber wird die Methode „createWriter“ aufgerufen, die für das Befüllen der Datei verantwortlich ist. Über eine weitere Funktion, welche über „createWriter()“ aufgerufen wird, wird ein Blob erstellt, der im Beispiel ein einfacher Text-Blob ist. Dem Blob-Objekt werden neben dem Dateiinhalt ein Objektliteral mit Angabe des Dateityps übergeben. Anschließend wird das Blob-Objekt per „write()“ in die Datei geschrieben.

Um eine Datei aus dem Dateisystem wieder zu löschen, gibt es die Methode „remove()“.

function dateispeichern(dateisystem) {
  dateisystem.root.getFile("info.txt", {create: false}, function(datei) { datei.remove(function() {}); })
}

Die Methode erwartet – wie auch „createWriter()“ – eine Funktion. Diese kann jedoch leer sein, da beim Löschen keine weiteren Angaben nötig sind.

Verzeichnisse erstellen

Analog zu „getFile()“ gibt es für Verzeichnisse die Methode „getDirectory()“. Sie funktioniert nach demselben Prinzip wie „getFile()“. Hiermit ist es möglich, Verzeichnisse zu erstellen und auch wieder zu löschen.

function dateispeichern(dateisystem) {
  dateisystem.root.getDirectory("demo", {create: true}, function() {});
}

Im Beispiel wird das Verzeichnis „demo“ erstellt. Natürlich ist es ebenso möglich, eine Datei in einem bestimmten Verzeichnis zu erstellen.

function dateispeichern(dateisystem) {
  dateisystem.root.getFile("/demo/info.txt", {create: true});
};

Mit der Methode „moveTo()“ können überdies Dateien in andere Verzeichnisse verschoben werden. Dazu wird zunächst die Methode „getFile()“ aufgerufen, über welchen man die Datei definiert, die verschoben werden soll. Anschließend ruft man die Methode „getDirectory()“ auf, innerhalb derer per „moveTo()“ die Datei in das über „getDirectory()“ definierte Verzeichnis verschoben wird.

function dateispeichern(dateisystem) {
  dateisystem.root.getFile("info.txt", {}, function(datei) {
    dateisystem.root.getDirectory("demo/", {}, function(verzeichnis) {
      datei.moveTo(verzeichnis);
    });
  });
}

Die Methode „moveTo()“ dient auch zum Umbenennen von Dateien. Dazu wird die Methode alleine (also ohne „getDirectory()“) aufgerufen.

function dateispeichern(dateisystem) {
  dateisystem.root.getFile("info.txt", {}, function(datei) {
    datei.moveTo(dateisystem.root, "neu.txt");
  });
}

Dateien im Browser aufrufen

Da die erzeugten Dateien und Verzeichnisse innerhalb eines geschützten Bereichs liegen, lassen sie sich nicht wie normale lokale Dateien im Browser aufrufen. Stattdessen gibt es ein eigenes Protokoll, über welches man Lesezugriff auf die Dateien nimmt. So lassen sie sich in ein Dokument einbinden oder direkt über die Adresszeile des Browsers aufrufen.

filesystem:http://www.example.com/persistent/info.txt
filesystem:http://www.example.com/temporary/info.txt

Die URL für lokale Dateien beginnt immer mit „filesystem:“. Es folgt die Domain der Website mit vorangestelltem HTTP-Protokoll. Da temporäre und dauerhaft gespeicherte Dateien unterschiedlich abgespeichert werden, folgt die Angabe des Speicherortes („persistent“ für dauerhaft gespeicherte und „temporary“ für vorübergehend gespeicherte Dateien). Anschließend folgen die Verzeichnisse und Dateien, die innerhalb des Dateisystems angelegt wurden.

FileSystem im Blick mit Chromes Entwicklertools

Die Entwicklertools im Chrome sind oftmals eine gute Hilfe, um beispielsweise Cookies und andere von einer Website gespeicherte Informationen nachvollziehen zu können. Auch die per FileSystem-API gespeicherten Dateien lassen sich mit den Entwicklertools darstellen – allerdings unter einer Voraussetzung. Die Unterstützung der FileSystem-API durch die Entwicklertools ist derzeit noch experimentell, weshalb sie zunächst freigeschaltet werden muss.

Dazu ruft man per Adresszeile „chrome://flags/“ auf und aktiviert „Entwicklertool-Experimente aktivieren“. Nach einem Neustart findet man in den Einstellungen der Entwicklertools den Bereich „Experimente“, über den sich „FileSystem inspection“ aktivieren lässt. Anschließend findet man im Reiter „Ressources“ der Entwicklertools den Punkt „FileSystem“, der alle per API angelegte Verzeichnisse und Dateien darstellt.

filesystem_devtools
Darstellung der FileSystem-Dateien in Chromes Entwicklertools
Die Entwicklertools stellen die Verzeichnisse und Dateien nur da. Ein Bearbeiten oder Löschen ist nicht möglich.

Anwendungsfälle

Der Einsatz der FileSystem-API bietet sich immer dann an, wenn zum Beispiel Dateien – vor allem größere Dateien – für einen dauerhaften oder späteren Einsatz bereitgestellt werden sollen. Es lassen sich beispielsweise Videodateien herunterladen und später ansehen. Der Vorteil zum einfachen Download der Dateien besteht darin, dass sie innerhalb der Website dargestellt werden können.

Auch webbasierte E-Mail- und Textverarbeitungsprogramme können die API nutzen, um Dateien nicht server-, sondern clientseitig zu speichern, beziehungsweise zwischenzuspeichern.

5 Kommentare zu “FileSystem-API: Dateien erstellen und lokal speichern mit JavaScript und Webkit”

puh…
Ich seh schon die Sicherheitslücken vor mir:
– genehmigte Websites schalten Banner, die dann beliebige, unkontrollierte Dinge tun
-gekaperte Websites, die dann beliebigen Content in mein System schreiben können und mit Nutzerrechten (was ja grad bei Win häufig Admin-Rechte sind) ausgeführt werden
-Man-in-the-middle Attacken
– Abhörwanzen von “interessierter” Stelle
Der Schutz der API vor Zugriff auf beliebige Ordner des Rechners ist da nur ein Tropfen auf den heißen Stein.
Sorry, prinzipiell ist so etwas rein aus Entwicklersicht toll, aber die damit einhergehenden Probleme sollte man deswegen nicht außer Acht lassen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.