Mit der HTML5-Dateisystem-API spielen

HTML5 bietet uns eine ganze Reihe neuer Möglichkeiten, z. B. das Zeichnen mit einer Leinwand, die Implementierung von Multimedia mit den Audio- und Video-APIs usw. Eines dieser noch relativ neuen Tools ist die Dateisystem-API. Dadurch haben wir Zugriff auf einen Sandkastenbereich des lokalen Dateisystems des Benutzers und schließen so die Lücke zwischen Desktop- und Webanwendungen noch weiter! Im heutigen Tutorial gehen wir durch die Grundlagen dieser neuen und aufregenden API und untersuchen die häufigsten Aufgaben des Dateisystems. Lass uns anfangen!


Einführung

Wir müssen nicht länger eine bestimmte Software herunterladen und installieren, um sie verwenden zu können. Mit einem Webbrowser und einer Internetverbindung können wir jede Webanwendung jederzeit und überall auf jeder Plattform verwenden.

Kurz gesagt, Web-Apps sind cool. Im Vergleich zu Desktop-Apps weisen sie jedoch immer noch eine erhebliche Schwachstelle auf: Sie haben keine Möglichkeit, Daten zu strukturieren und in einer strukturierten Hierarchie von Ordnern zu organisieren - einem echten Dateisystem. Glücklicherweise kann dies mit der neuen Dateisystem-API geändert werden. Diese API ermöglicht Webanwendungen den kontrollierten Zugriff auf ein privates lokales Dateisystem "Sandbox", in dem sie Dateien schreiben und lesen, Verzeichnisse erstellen und auflisten können usw. Zum Zeitpunkt dieses Schreibens unterstützt nur der Chrome-Browser von Google die "vollständige" Implementierung der Dateisystem-API, dennoch sollte er als leistungsstarke und praktische Form des lokalen Speichers untersucht werden.

Die Dateisystem-API gibt es in zwei verschiedenen Versionen. Die asynchrone API, die für normale Anwendungen nützlich ist, und die synchrone API, die für die Verwendung mit Web-Workern reserviert ist. In diesem Tutorial untersuchen wir ausschließlich die asynchrone Version der API.


Schritt 1 - Erste Schritte

Als ersten Schritt erhalten Sie Zugriff auf das HTML5-Dateisystem, indem Sie a LocalFile Systemobjekt mit der window.requestFileSystem () globale Methode:

window.requestFileSystem (type, size, successCallback, opt_errorCallback)

Eine Webanwendung kann nicht über das lokale Stammverzeichnis hinaus "ausbrechen".

Als erste beiden Parameter geben Sie die Lebensdauer und Größe des gewünschten Dateisystems an. EIN PERSISTENT Das Dateisystem eignet sich für Web-Apps, die Benutzerdaten dauerhaft speichern möchten. Der Browser löscht sie nur auf ausdrückliche Anfrage des Benutzers. EIN TEMPORARY Das Dateisystem ist für Web-Apps geeignet, die Daten zwischenspeichern möchten, aber dennoch ausgeführt werden können, wenn der Webbrowser das Dateisystem löscht. Die Größe des Dateisystems wird in Byte angegeben und sollte eine angemessene Obergrenze für die zu speichernde Datenmenge sein.

Der dritte Parameter ist eine Rückruffunktion, die ausgelöst wird, wenn der Benutzeragent erfolgreich ein Dateisystem bereitstellt. Ihr Argument ist a Dateisystem Objekt. Und schließlich können wir eine optionale Rückruffunktion hinzufügen, die aufgerufen wird, wenn ein Fehler auftritt oder die Anforderung eines Dateisystems abgelehnt wird. Ihr Argument ist a Dateifehler Objekt. Obwohl dieser Parameter optional ist, ist es immer eine gute Idee, Fehler für Benutzer abzufangen, da an verschiedenen Stellen Fehler auftreten können.

Das Dateisystem, das mit diesen Funktionen erhalten wird, hängt von der Herkunft des Dokuments ab. Alle Dokumente oder Web-Apps mit demselben Ursprung (Host, Port und Protokoll) nutzen ein Dateisystem gemeinsam. Zwei Dokumente oder Anwendungen unterschiedlicher Herkunft verfügen über völlig unterschiedliche und getrennte Dateisysteme. Ein Dateisystem ist auf eine einzelne Anwendung beschränkt und kann nicht auf die gespeicherten Daten einer anderen Anwendung zugreifen. Es ist auch von den restlichen Dateien auf der Festplatte des Benutzers isoliert, was eine gute Sache ist: Es gibt keine Möglichkeit, dass eine Webanwendung über das lokale Stammverzeichnis hinaus ausbricht oder auf beliebige Dateien zugreift.

Sehen wir uns ein Beispiel an:

window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; window.requestFileSystem (window.TEMPORARY, 5 * 1024 * 1024, initFS, errorHandler); function initFS (fs) alert ("Willkommen im Dateisystem! Showtime :)"); // Nur um zu überprüfen, ob alles in Ordnung ist :) // Platziere die Funktionen, die Sie hier lernen werden function errorHandler () console.log ('Ein Fehler ist aufgetreten'); 

Dadurch wird ein temporäres Dateisystem mit 5 MB Speicherplatz erstellt. Dann steht eine Erfolgsrückruffunktion zur Verfügung, die wir zum Betrieb unseres Dateisystems verwenden werden. Und natürlich wird auch ein Fehlerbehandler hinzugefügt - nur für den Fall, dass etwas schief geht. Hier die errorHandler () Funktion ist zu generisch. Wenn Sie möchten, können Sie also eine leicht optimierte Version erstellen, die dem Leser eine aussagekräftigere Fehlermeldung gibt:

function errorHandler (err) var msg = 'Ein Fehler ist aufgetreten:'; switch (err.code) case FileError.NOT_FOUND_ERR: msg + = 'Datei oder Verzeichnis nicht gefunden'; brechen; case FileError.NOT_READABLE_ERR: msg + = 'Datei oder Verzeichnis nicht lesbar'; brechen; case FileError.PATH_EXISTS_ERR: msg + = 'Datei oder Verzeichnis existiert bereits'; brechen; case FileError.TYPE_MISMATCH_ERR: msg + = 'Ungültiger Dateityp'; brechen; Voreinstellung: msg + = 'Unknown Error'; brechen; ; console.log (msg); ;

Das Dateisystemobjekt, das Sie erhalten, hat eine Name (eindeutiger Name für das Dateisystem, vom Browser vergeben) und Wurzel Eigenschaft, die sich auf das Stammverzeichnis des Dateisystems bezieht. Das ist ein DirectoryEntry Objekt, und es kann verschachtelte Verzeichnisse haben, die selbst durch dargestellt werden DirectoryEntry Objekte. Jedes Verzeichnis im Dateisystem kann Dateien enthalten, die durch dargestellt werden FileEntry Objekte. Das DirectoryEntry Objekt definiert Methoden zum Erhalten DirectoryEntry und FileEntry Objekte nach Pfadnamen (sie erstellen optional neue Verzeichnisse oder Dateien, wenn Sie einen Namen angeben, der nicht vorhanden ist). DirectoryEntry definiert auch a createReader () Factory-Methode, die a zurückgibt DirectoryReader Objekt zum Auflisten des Inhalts eines Verzeichnisses. Das FileEntry Klasse definiert eine Methode zum Erhalten der Datei Objekt (ein Blob), das den Inhalt einer Datei darstellt. Sie können dann eine FileReader Objekt zum Lesen der Datei. FileEntry definiert eine andere Methode, um a zurückzugeben FileWriter Objekt, mit dem Sie Inhalte in eine Datei schreiben können.

Phuh… klingt kompliziert? Mach dir keine Sorgen. Alles wird klarer, wenn wir durch die nachstehenden Beispiele vorgehen.


Schritt 2 - Mit Verzeichnissen arbeiten

Natürlich müssen Sie in einem Dateisystem zuerst einige Buckets oder Verzeichnisse erstellen. Obwohl das Stammverzeichnis bereits vorhanden ist, möchten Sie nicht alle Dateien dort ablegen. Verzeichnisse werden vom erstellt DirectoryEntry Objekt. Im folgenden Beispiel erstellen wir ein Verzeichnis mit dem Namen Unterlagen, im Wurzelverzeichnis:

fs.root.getDirectory ('Documents', create: true, function (dirEntry) alert ('Sie haben gerade das Verzeichnis' + dirEntry.name + 'erstellt.');, errorHandler);

Das getDirectory () Diese Methode wird sowohl zum Lesen als auch zum Erstellen von Verzeichnissen verwendet. Als ersten Parameter können Sie entweder einen Namen oder einen Pfad als Verzeichnis zum Nachschlagen oder Erstellen angeben. Wir setzen das zweite Argument auf wahr, weil wir versuchen, ein Verzeichnis zu erstellen - kein bestehendes zu lesen. Und am Ende fügen wir einen Fehlerrückruf hinzu.

So weit, ist es gut. Wir haben ein Verzeichnis. Lassen Sie uns nun ein Unterverzeichnis hinzufügen. Die Funktion ist mit einem Unterschied genau gleich: Wir ändern das erste Argument von 'Documents' in 'Documents / Music'. Leicht genug; Was aber, wenn Sie einen Unterordner erstellen möchten, Himmel, mit zwei übergeordneten Ordnern, Bilder und Natur, in der Unterlagen Mappe? Wenn Sie 'eingebenDokumente / Bilder / Natur / Himmel'für das Pfadargument erhalten Sie eine Fehlermeldung, da Sie kein Verzeichnis erstellen können, wenn das unmittelbare übergeordnete Element nicht vorhanden ist. Eine Lösung hierfür ist, jeden Ordner einzeln zu erstellen: Bilder Innerhalb Unterlagen, Natur Innerhalb Bilder, und dann Himmel Innerhalb Natur. Dies ist jedoch ein sehr langsamer und unpraktischer Prozess. Es gibt eine bessere Lösung: Eine Funktion erstellen, die alle erforderlichen Ordner automatisch erstellt.

function createDir (rootDir, Ordner) rootDir.getDirectory (Ordner [0], create: true), Funktion (dirEntry) if (folder.length) createDir (dirEntry, folder.slice (1)); errorHandler); ; createDir (fs.root, 'Documents / Images / Nature / Sky /'. split ('/'));

Mit diesem kleinen Trick müssen wir nur einen vollständigen Pfad angeben, der die Ordner darstellt, die wir erstellen möchten. Jetzt die Himmel Das Verzeichnis wurde erfolgreich erstellt, und Sie können andere Dateien oder Verzeichnisse darin erstellen.

Nun ist es Zeit zu überprüfen, was wir in unserem Dateisystem haben. Wir schaffen eine DirectoryReader Objekt und verwenden Sie die readEntries () Methode, um den Inhalt des Verzeichnisses zu lesen.

fs.root.getDirectory ('Documents', , Funktion (dirEntry) 
var dirReader = dirEntry.createReader (); dirReader.readEntries (Funktion (Einträge)
für (var i = 0; i < entries.length; i++) var entry = entries[i]; if (entry.isDirectory) console.log('Directory: ' + entry.fullPath); else if (entry.isFile) console.log('File: ' + entry.fullPath); , errorHandler); , errorHandler);

Im obigen Code steht der isDirectory und isFile Eigenschaften werden verwendet, um eine unterschiedliche Ausgabe für Verzeichnisse bzw. Dateien zu erhalten. Zusätzlich verwenden wir die vollständigen Pfad Eigenschaft, um den vollständigen Pfad des Eintrags anstelle des Namens zu erhalten.

Es gibt zwei Möglichkeiten, a zu entfernen DirectoryEntry aus dem Dateisystem: Löschen() und removeRecursively (). Das erste entfernt ein bestimmtes Verzeichnis nur, wenn es leer ist. Andernfalls erhalten Sie eine Fehlermeldung.

fs.root.getDirectory ('Documents / Music', , function (dirEntry) dirEntry.remove (function () console.log ('Verzeichnis wurde erfolgreich entfernt.');, errorHandler);, errorHandler);

Wenn die Musik Ordner enthält Dateien, dann müssen Sie die zweite Methode verwenden, die das Verzeichnis und seinen gesamten Inhalt rekursiv löscht.

fs.root.getDirectory ('Documents / Music', , function (dirEntry) dirEntry.removeRecursively (function () console.log ('Das Verzeichnis wurde erfolgreich entfernt.');, errorHandler);, errorHandler);

Schritt 3 - Mit Dateien arbeiten

Nun, da wir wissen, wie Verzeichnisse erstellt werden, ist es an der Zeit, sie mit Dateien zu füllen!

Im folgenden Beispiel wird eine leere erstellt test.txt im Wurzelverzeichnis:

fs.root.getFile ('test.txt', create: true, exclusive: true), Funktion (fileEntry) alert ('Eine Datei' + fileEntry.name + 'wurde erfolgreich erstellt.');, errorHandler) ;

Das erste Argument zu eine Datei bekommen() kann ein absoluter oder relativer Pfad sein, muss jedoch gültig sein. Beispielsweise ist es ein Fehler, zu versuchen, eine Datei zu erstellen, wenn das unmittelbare übergeordnete Element nicht vorhanden ist. Das zweite Argument ist ein Objektliteral, das das Verhalten der Funktion beschreibt, wenn die Datei nicht vorhanden ist. In diesem Beispiel, erstellen: wahr erstellt die Datei, wenn sie nicht vorhanden ist, und gibt einen Fehler aus (exklusiv: wahr). Andernfalls wenn create: false, Die Datei wird einfach abgerufen und zurückgegeben.

Eine leere Datei zu haben ist jedoch nicht sehr nützlich. Fügen wir also etwas Inhalt hinzu. Wir können die verwenden FileWriter Objekt dafür.

fs.root.getFile ('test.txt', create: false, Funktion (fileEntry) fileEntry.createWriter (Funktion (fileWriter)) window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder; var bb = neuer BlobBuilder; (); bb.append ('Dateisystem-API ist fantastisch!'); fileWriter.write (bb.getBlob ('text / plain'));, errorHandler);, errorHandler);

Oben holen wir das ab test.txt Datei und erstellen Sie eine FileWriter Objekt dafür. Wir fügen dann Inhalt hinzu, indem wir einen neuen erstellen BlobBuilder Objekt und mit der schreiben() Methode von FileWriter.

Berufung eine Datei bekommen() ruft nur ein FileEntry. Der Inhalt der Datei wird nicht zurückgegeben. Wenn wir also den Inhalt der Datei lesen wollen, müssen wir die Datei Objekt und die FileReader Objekt.

fs.root.getFile ('test.txt', , Funktion (fileEntry) fileEntry.file (Funktion (Datei) var reader = neuer FileReader (); reader.onloadend = function (e) alert (this.) Ergebnis);; reader.readAsText (Datei);, errorHandler);, errorHandler);

Wir haben einige Inhalte in unsere Datei geschrieben, aber wenn Sie später mehr hinzufügen möchten? Um Daten an eine vorhandene Datei anzuhängen, die FileWriter wird wieder verwendet. Wir können den Writer mit dem Ende der Datei neu positionieren suchen() Methode. suchen akzeptiert einen Byte-Offset als Argument und setzt die Position des Datei-Schreibers auf diesen Offset.

fs.root.getFile ('test.txt', create: false, Funktion (fileEntry) fileEntry.createWriter (function (fileWriter)) fileWriter.seek (fileWriter.length); window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder; var bb = new BlobBuilder (); bb.append ('Ja, das ist es!'); fileWriter.write (bb.getBlob ('text / plain'));, errorHandler);, errorHandler) ;

Um eine Datei aus dem Dateisystem zu entfernen, rufen Sie einfach auf entry.remove (). Das erste Argument für diese Methode ist eine Nullparameter-Rückruffunktion, die aufgerufen wird, wenn die Datei erfolgreich gelöscht wurde. Die zweite ist ein optionaler Fehlerrückruf, falls Fehler auftreten.

fs.root.getFile ('test.txt', create: false, Funktion (fileEntry) fileEntry.remove (function () console.log ('Datei wurde erfolgreich entfernt.');, errorHandler);, errorHandler);

Schritt 4 - Dateien und Verzeichnisse bearbeiten

FileEntry und DirectoryEntry Verwenden Sie dieselben API-Methoden zum Kopieren, Verschieben und Umbenennen von Einträgen. Es gibt zwei Methoden, die Sie für diese Vorgänge verwenden können: Kopieren nach() und ziehen nach(). Beide akzeptieren die gleichen Parameter:

copyTo (parentDirEntry, opt_newName, opt_successCallback, opt_errorCallback); moveTo (parentDirEntry, opt_newName, opt_successCallback, opt_errorCallback);

Der erste Parameter ist der übergeordnete Ordner, in den der Eintrag verschoben / kopiert werden soll. Der zweite ist ein optionaler neuer Name für den verschobenen / kopierten Eintrag, der tatsächlich erforderlich ist, wenn Sie einen Eintrag in denselben Ordner kopieren. Andernfalls erhalten Sie eine Fehlermeldung. Der dritte und der vierte Parameter wurden zuvor erläutert.

Sehen wir uns einige einfache Beispiele an. In der folgenden kopieren wir die Datei test.txt von dem Wurzel zum Unterlagen Verzeichnis.

Funktionskopie (currDir, srcEntry, destDir) currDir.getFile (srcEntry, , Funktion (fileEntry) currDir.getDirectory (destDir, ), Funktion (dirEntry) fileEntry.copyTo (dirEntry);, errorHandler; , errorHandler);  copy (fs.root, 'test.txt', 'Documents /'));

Das nächste Beispiel bewegt sich test.txt zu Unterlagen, anstatt es zu kopieren:

function move (currDir, srcEntry, dirName) currDir.getFile (srcEntry, , Funktion (fileEntry) currDir.getDirectory (dirName, ) Funktion (dirEntry) fileEntry.moveTo (dirEntry);, errorHandler; , errorHandler);  move (fs.root, 'test.txt', 'Documents /'));

Das folgende Beispiel wird umbenannt test.txt zu text.txt:

Funktion umbenennen (currDir, srcEntry, newName) currDir.getFile (srcEntry, , Funktion (fileEntry) fileEntry.moveTo (currDir, newName);, errorHandler);  Umbenennen (fs.root, 'test.txt', 'text.txt');

Lern mehr

In diesem einführenden Tutorial haben wir nur die Oberfläche der verschiedenen Dateisystemschnittstellen verkratzt. Wenn Sie mehr erfahren und tiefer in die Dateisystem-API einsteigen möchten, lesen Sie die Spezifikationen des W3C:

  • Datei-API: Verzeichnisse und System
  • Datei-API: Writer
  • Datei-API

Nachdem Sie nun ein grundlegendes Verständnis dafür haben, was die Dateisystem-API ist und wie sie verwendet werden kann, sollte die API-Dokumentation erheblich verständlicher sein, was auf den ersten Blick etwas verwirrend sein kann.


Fazit

Die Filesystem-API ist eine leistungsstarke und benutzerfreundliche Technologie, die Webentwicklern eine ganze Reihe neuer Möglichkeiten beim Erstellen von Webanwendungen bietet. Zwar ist es noch recht neu und wird nicht von allen großen Browsern unterstützt, aber dies wird sich in Zukunft sicherlich ändern. Sie könnten genauso gut einen Vorsprung bekommen!