Toying Med HTML5 File System API

HTML5 ger oss en hel del nya möjligheter, till exempel ritning med duk, implementering av multimedia med ljud- och video API, och så vidare. Ett av dessa verktyg, som fortfarande är relativt nytt, är File System API. Det ger oss tillgång till en sandlåda del av användarens lokala filsystem och därigenom fyller klyftan mellan skrivbord och webbapplikationer ännu längre! I dagens handledning går vi igenom grunderna i det här nya och spännande API, och utforskar de vanligaste filsystemuppgifterna. Låt oss börja!


Introduktion

Vi behöver inte längre ladda ner och installera en viss mjukvara för att kunna använda den. Bara en webbläsare och en internetanslutning ger oss möjlighet att använda vilken webbapplikation som helst, var som helst, var som helst och på vilken plattform som helst.

Kort sagt, webbapplikationer är coola; men jämfört med skrivbordsprogram har de fortfarande en signifikant svaghet: de har inte ett sätt att interagera och organisera data till en strukturerad mapphierarki - ett riktigt filsystem. Lyckligtvis kan det här ändras med det nya Filsystem API. Detta API ger webbapplikationer kontrollerad åtkomst till ett privat lokalt filsystem "sandbox", där de kan skriva och läsa filer, skapa och lista kataloger, och så vidare. Även om Google-Chrome-webbläsaren bara stöder den fullständiga implementeringen av File System API vid skrivandet av detta skrivande, förtjänar det fortfarande att studeras som en kraftfull och bekväm form av lokal lagring.

Filsystemet API finns i två olika versioner. Det asynkrona API, vilket är användbart för normala applikationer, och det synkrona API, reserverat för användning med webarbetare. I samband med denna handledning utforskar vi uteslutande den asynkrona versionen av API: n.


Steg 1 - Komma igång

Ditt första steg är att få tillgång till HTML5-filsystemet genom att be om a LocalFile Systemobjekt, med hjälp av window.requestFileSystem () global metod:

window.requestFileSystem (typ, storlek, framgångCallback, opt_errorCallback)

Det finns inget sätt för en webbapplikation att "bryta ut" bortom den lokala rotkatalogen.

Som de två första parametrarna anger du livstiden och storleken på filsystemet du vill ha. en BESTÄNDIG filsystem är lämpligt för webbapps som vill lagra användardata permanent. Webbläsaren tar inte bort den, med undantag för användarens uttryckliga förfrågan. en TILLFÄLLIGA filsystem är lämpligt för webbapps som vill cache data, men kan fortfarande fungera om webbläsaren raderar filsystemet. Filsystemets storlek är specificerat i byte och bör vara en rimlig övre gräns för hur mycket data du behöver lagra.

Den tredje parametern är en återuppringningsfunktion som utlöses när användaragenten framgångsrikt tillhandahåller ett filsystem. Dess argument är a Filsystem objekt. Och till sist kan vi lägga till en valfri återuppringningsfunktion, som kallas när ett fel inträffar, eller begäran om ett filsystem avvisas. Dess argument är a FileError objekt. Även om denna parameter är valfri är det alltid en bra idé att fånga fel för användarna, eftersom det finns ett antal platser där saker kan gå fel.

Filsystemet som erhålls med dessa funktioner beror på innehållet i det innehållande dokumentet. Alla dokument eller webbapps från samma ursprung (värd, port och protokoll) delar ett filsystem. Två dokument eller program från olika ursprung har helt distinkta och ojämna filsystem. Ett filsystem är begränsat till en enda applikation och kan inte komma åt en annan applikations lagrade data. Det är också isolerat från resten av filerna på användarens hårddisk, vilket är bra: det finns inget sätt för en webbapplikation att "bryta ut" bortom den lokala rotkatalogen eller på annat sätt komma åt godtyckliga filer.

Låt oss granska ett exempel:

window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; window.requestFileSystem (window.TEMPORARY, 5 * 1024 * 1024, initFS, errorHandler); funktion initFS (fs) alert ("Välkommen till Filesystem! Det är showtime :)"); // Bara för att kontrollera om allt är OK :) // Placera de funktioner du kommer att lära dig här här FunktionsfelHandler () Console.log ('Ett fel inträffat'); 

Detta skapar ett temporärt filsystem med 5 MB lagring. Det ger då en återuppringningsfunktion, som vi kommer att använda för att driva vårt filsystem. Och naturligtvis är en felhanterare också tillagt - bara om något går fel. Här, den errorhandler () funktionen är för generisk. Så om du vill kan du skapa en lite optimerad version, vilket ger läsaren ett mer beskrivande felmeddelande:

funktion errorHandler (err) var msg = 'Ett fel inträffade:'; switch (err.code) case FileError.NOT_FOUND_ERR: msg + = 'Fil eller katalog hittades inte'; ha sönder; case FileError.NOT_READABLE_ERR: msg + = 'Fil eller katalog ej läsbar'; ha sönder; case FileError.PATH_EXISTS_ERR: msg + = 'Fil eller katalog finns redan'; ha sönder; fall FileError.TYPE_MISMATCH_ERR: msg + = 'Ogiltig filtyp'; ha sönder; default: msg + = 'Okänt fel'; ha sönder; ; console.log (msg); ;

Filsystemobjektet du får har a namn (ett unikt namn för filsystemet, tilldelat av webbläsaren) och rot egenskap som hänvisar till filsystemets rotkatalog. Det här är en DirectoryEntry objekt, och det kan ha kapslade kataloger som själva representeras av DirectoryEntry objekt. Varje katalog i filsystemet kan innehålla filer representerade av FileEntry objekt. De DirectoryEntry objekt definierar metoder för att erhålla DirectoryEntry och FileEntry objekt med söknamn (de skapar eventuellt nya kataloger eller filer om du anger ett namn som inte existerar). DirectoryEntry definierar också a createReader () fabriksmetod som returnerar a DirectoryReader objekt för att lista innehållet i en katalog. De FileEntry klassen definierar en metod för att erhålla Fil objekt (ett Blob) som representerar innehållet i en fil. Du kan då använda en Filereader objekt att läsa filen. FileEntry definierar en annan metod för att returnera a Filewriter objekt som du kan använda för att skriva innehåll i en fil.

Phhew ... låter komplicerat? Oroa dig inte. Allt kommer att bli tydligare när vi går igenom exemplen nedan.


Steg 2 - Arbeta med kataloger

Det är självklart att det första du behöver skapa i ett filsystem är några hinkar eller kataloger. Även om rotkatalogen redan existerar, vill du inte placera alla dina filer där. Kataloger skapas av DirectoryEntry objekt. I följande exempel skapar vi en katalog som heter Dokument, i rotkatalogen:

fs.root.getDirectory ('Dokument', skapa: true, funktion (dirEntry) alert ('Du har just skapat katalogen' + dirEntry.name + '.');, errorHandler);

De getDirectory () Metoden används både för att läsa och skapa kataloger. Som den första parametern kan du skicka antingen ett namn eller en sökväg som katalogen att leta upp eller skapa. Vi ställer det andra argumentet till Sann, eftersom vi försöker skapa en katalog - läs inte en befintlig. Och i slutet lägger vi till en återuppringning av felet.

Än så länge är allt bra. Vi har en katalog; låt oss nu lägga till en underkatalog. Funktionen är exakt densamma med en skillnad: Vi ändrar det första argumentet från "Dokument" till "Dokument / Musik". Lätt nog men vad händer om du vill skapa en undermapp, Himmel, med två föräldramappar, Bilder och Natur, inuti Dokument mapp? Om du skriver "Dokument / Bilder / Nature / Sky"för sökvägsargumentet får du ett fel eftersom du inte kan skapa en katalog när den omedelbara föräldern inte existerar. En lösning för detta är att skapa varje mapp en efter en: Bilder inuti Dokument, Natur inuti Bilder, och då Himmel inuti Natur. Men det här är en väldigt långsam och obekväm process. Det finns en bättre lösning: att skapa en funktion som automatiskt skapar alla nödvändiga mappar.

funktion (dirEntry) if (folders.length) createDir (dirEntry, folders.slice (1), errorhandler); ; createDir (fs.root, 'Documents / Images / Nature / Sky /'. split ('/'));

Med detta lilla trick är allt vi behöver göra för att ge en fullständig sökväg som representerar de mappar som vi vill skapa. Nu den Himmel katalog skapades med framgång, och du kan skapa andra filer eller kataloger inom den.

Nu är det dags att kolla vad vi har i vårt filsystem. Vi skapar en DirectoryReader objekt och använd readEntries () Metod för att läsa innehållet i katalogen.

fs.root.getDirectory ('Documents', , funktion (dirEntry) 
var dirReader = dirEntry.createReader (); dirReader.readEntries (funktion (poster)
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);

I koden ovan är isDirectory och ISFILE Egenskaper används för att få en annan utgång för respektive kataloger och filer. Dessutom använder vi fullständig sökväg egendom för att få hela vägen till posten, istället för sitt namn.

Det finns två sätt att ta bort en DirectoryEntry från filsystemet: ta bort() och removeRecursively (). Den första tar bort en viss katalog endast om den är tom. Annars får du ett fel.

fs.root.getDirectory ('Documents / Music', , funktionen (dirEntry) dirEntry.remove (funktion () console.log ('Katalog borttaget framgångsrikt');, errorHandler);, errorHandler);

Om musik mappen har filer inom den, då måste du använda den andra metoden, som rekursivt tar bort katalogen och hela dess innehåll.

fs.root.getDirectory ('Documents / Music', , funktion (dirEntry) dirEntry.removeRecursively (funktion () console.log ('Katalog successively removed.');, errorHandler);, errorHandler);

Steg 3 - Arbeta med filer

Nu när vi vet hur man skapar kataloger är det dags att fylla dem med filer!

Följande exempel skapar en tom test.txt i rotkatalogen:

fs.root.getFile ('test.txt', skapa: true, exclusive: true, funktion (fileEntry) alert ('En fil' + fileEntry.name + 'skapades med framgång.');, errorHandler) ;

Det första argumentet till Få fil() kan vara en absolut eller relativ sökväg, men den måste vara giltig. Det är till exempel ett fel att försöka skapa en fil när den omedelbara föräldern inte existerar. Det andra argumentet är ett objekt bokstavligt, som beskriver funktionens beteende om filen inte existerar. I detta exempel, skapa: true skapar filen om den inte existerar och kastar ett fel om det gör det (exklusivt: sant). Annars, om skapa: false, filen hämtas enkelt och returneras.

Att ha en tom fil är dock inte särskilt användbar. så låt oss lägga till lite innehåll inuti. Vi kan använda Filewriter motsätta sig detta.

fs.root.getFile ('test.txt', skapa: false, funktion (fileEntry) fileEntry.createWriter (funktion (fileWriter) window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder; var bb = ny BlobBuilder (); bb.append ('Filsystem API är fantastiskt!'); fileWriter.write (bb.getBlob ('text / plain')), errorHandler);, errorHandler);

Ovan hämtar vi test.txt fil och skapa en Filewriter motsätta sig det. Vi lägger sedan till innehåll på det genom att skapa en ny BlobBuilder objekt och använda skriva() metod av Filewriter.

Kallelse Få fil() hämtar bara a FileEntry. Det returnerar inte innehållet i filen. Så, om vi vill läsa innehållet i filen, måste vi använda Fil objekt och Filereader objekt.

fs.root.getFile ('test.txt', , funktion (fileEntry) fileEntry.file (funktion (fil) var reader = new FileReader (); reader.onloadend = function (e) alert (this. resultat);; läsare.readAsText (fil);, errorHandler);, errorHandler);

Vi har skrivit lite innehåll till vår fil, men vad om önskan att lägga till mer vid ett senare tillfälle? För att lägga till data i en befintlig fil, Filewriter används en gång till. Vi kan omplacera författaren till slutet av filen med hjälp av söka() metod. söka accepterar en byte-offset som ett argument, och ställer in filförfattarens position till den förskjutningen.

fs.root.getFile ('test.txt', skapa: false, funktion (fileEntry) fileEntry.createWriter (funktion (fileWriter) fileWriter.seek (fileWriter.length); window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder; var bb = ny BlobBuilder (); bb.append ('Ja, det är!'); fileWriter.write (bb.getBlob ('text / plain')), errorHandler);, errorHandler) ;

För att ta bort en fil från filsystemet, ring bara entry.remove (). Det första argumentet för denna metod är en nollparameterns återuppringningsfunktion, som kallas när filen har tagits bort. Den andra är ett valfritt återkommande fel om några fel uppstår.

fs.root.getFile ('test.txt', skapa: false, funktion (fileEntry) fileEntry.remove (function () console.log ('File successufully removed.';, errorHandler); errorhandler);

Steg 4 - Manipulera filer och kataloger

FileEntry och DirectoryEntry dela samma API-metoder för att kopiera, flytta och byta namn på poster. Det finns två metoder du kan använda för dessa operationer: kopia till() och flytta till(). De båda accepterar exakt samma parametrar:

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

Den första parametern är föräldermappen för att flytta / kopiera inmatningen till. Den andra är ett valfritt nytt namn för att ge den flyttade / kopierade posten, som faktiskt krävs när du kopierar en post i samma mapp; annars får du ett fel. De tredje och fjärde parametrarna förklarades tidigare.

Låt oss granska några enkla exempel. I det följande kopierar vi filen test.txt från rot till Dokument katalog.

Funktions kopia (currDir, srcEntry, destDir) currDir.getFile (srcEntry, , funktion (fileEntry) currDir.getDirectory (destDir, , funktionen (dirEntry) fileEntry.copyTo (dirEntry);, errorHandler); , errorHandler);  kopia (fs.root, 'test.txt', 'Documents /');

Detta nästa exempel rör sig test.txt till Dokument, istället för att kopiera den:

Funktionsrörelse (currDir, srcEntry, dirName) currDir.getFile (srcEntry, , funktion (fileEntry) currDir.getDirectory (dirName, , funktion (dirEntry) fileEntry.moveTo (dirEntry);, errorHandler); , errorHandler);  flytta (fs.root, 'test.txt', 'Documents /');

Följande exempel byter namn på test.txt till text.txt:

funktion rename (currDir, srcEntry, newName) currDir.getFile (srcEntry, , funktion (fileEntry) fileEntry.moveTo (currDir, newName);, errorHandler);  byt namn (fs.root, "test.txt", "text.txt");

Läs mer

I den här inledande handledningen har vi bara repat ytan på de olika filsystemgränssnitten. Om du vill lära dig mer och gräva djupare i File System API, bör du se W3C-specifikationerna:

  • Fil API: kataloger och system
  • Fil API: Writer
  • Fil API

Nu när du har en grundläggande förståelse för vad Filsystem API är och hur det kan användas, bör det vara väsentligt lättare att förstå API-dokumentationen, vilket kan vara lite förvirrande vid första anblicken.


Slutsats

Filsystem API är en kraftfull och lättanvänd teknik som ger webbutvecklare en hel del nya möjligheter när man bygger webbapplikationer. Visserligen är det fortfarande ganska nytt och inte brett stöds av alla större webbläsare, men det kommer säkert att förändras i framtiden. Du kan lika bra få en start!