Toying Med HTML5 File System API

HTML5 gir oss en hel del nye muligheter, for eksempel tegning med lerret, implementering av multimedia med lyd- og video-APIer, og så videre. Et av disse verktøyene, som fortsatt er relativt nytt, er File System API. Det gir oss tilgang til en sandkasse av brukerens lokale filsystem, og dermed fylle gapet mellom desktop og web-applikasjoner enda mer! I dagens veiledning går vi gjennom grunnleggende om denne nye og spennende API-en, og utforsker de vanligste filsystemoppgaver. La oss komme i gang!


Introduksjon

Ikke lenger trenger vi å laste ned og installere et gitt stykke programvare for å kunne bruke det. Bare en nettleser og en internettforbindelse gir oss muligheten til å bruke et hvilket som helst webprogram, når som helst, hvor som helst og på hvilken som helst plattform.

Kort sagt, webapplikasjoner er kule; men i forhold til skrivebordsprogrammer har de fortsatt en betydelig svakhet: de har ikke mulighet til å samhandle og organisere data i et strukturert mapperhierarki - et ekte filsystem. Heldigvis, med den nye Filsystem-API, kan dette endres. Denne API gir webapplikasjoner kontrollert tilgang til et privat lokalt filsystem "sandkasse", der de kan skrive og lese filer, opprette og liste kataloger, og så videre. Selv om bare Google Chrome-nettleseren støtter den "fullstendige" implementeringen av Filsystem-APIen, fortjener den fortsatt å bli studert som en kraftig og praktisk form for lokal lagring.

Filsystemet API leveres i to forskjellige versjoner. Den asynkrone API, som er nyttig for vanlige applikasjoner, og den synkroniserte API, reservert for bruk med webarbeidere. I forbindelse med denne opplæringen vil vi utelukkende utforske den asynkrone versjonen av API.


Trinn 1 - Komme i gang

Ditt første skritt er å få tilgang til HTML5-filsystemet ved å be om a LocalFile Systemobjekt, bruk av window.requestFileSystem () global metode:

window.requestFileSystem (type, størrelse, suksessCallback, opt_errorCallback)

Det er ikke mulig for et webprogram å "bryte ut" utover den lokale rotkatalogen.

Som de to første parameterne angir du levetid og størrelse på filsystemet du vil ha. EN vedvarende filsystem er egnet for webapps som vil lagre brukerdata permanent. Nettleseren vil ikke slette den, med unntak av brukerens eksplisitte forespørsel. EN MIDLERTIDIG filsystem er egnet for webapper som vil cache data, men kan fortsatt fungere hvis nettleseren sletter filsystemet. Størrelsen på filsystemet er spesifisert i byte og bør være en rimelig øvre grense på mengden data du må lagre.

Den tredje parameteren er en tilbakeringingsfunksjon som utløses når brukeragenten vellykker et filsystem. Argumentet er a Filsystem gjenstand. Og til slutt kan vi legge til en valgfri tilbakeringingsfunksjon, som kalles når det oppstår en feil, eller forespørselen om et filsystem blir nektet. Argumentet er a FileError gjenstand. Selv om denne parameteren er valgfri, er det alltid en god idé å ta feil for brukere, da det er flere steder hvor ting kan gå galt.

Filsystemet som er oppnådd med disse funksjonene, avhenger av opprinnelsen til det inneholdende dokumentet. Alle dokumenter eller nettprogrammer fra samme opprinnelse (vert, port og protokoll) deler et filsystem. To dokumenter eller programmer fra forskjellige opprinnelser har helt forskjellige og uensartede filsystemer. Et filsystem er begrenset til en enkelt applikasjon og kan ikke få tilgang til en annen applikasjons lagrede data. Det er også isolert fra resten av filene på brukerens harddisk, noe som er bra: det er ikke mulig for et webprogram å "bryte ut" utover den lokale rotkatalogen eller på annen måte få tilgang til vilkårlig filer.

La oss se på et eksempel:

window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; window.requestFileSystem (window.TEMPORARY, 5 * 1024 * 1024, initFS, errorHandler); funksjon initFS (fs) alert ("Velkommen til Filesystem! Det er showtime :)"); // Bare for å sjekke om alt er greit :) // plasser funksjonene du vil lære deg her funksjon errorHandler () console.log ('En feil oppstod'); 

Dette skaper et midlertidig filsystem med 5 MB lagringsplass. Det gir en suksess tilbakeringingsfunksjon, som vi skal bruke til å operere vårt filsystem. Og selvfølgelig er en feilbehandler også lagt til - bare hvis noe går galt. Her, den Errorhandler () funksjonen er for generisk. Så hvis du vil, kan du opprette en litt optimalisert versjon, som gir leseren en mer beskrivende feilmelding:

funksjon errorHandler (err) var msg = 'En feil oppstod:'; bytt (err.code) case FileError.NOT_FOUND_ERR: msg + = 'Fil eller katalog ikke funnet'; gå i stykker; case FileError.NOT_READABLE_ERR: msg + = 'Fil eller katalog ikke lesbar'; gå i stykker; case FileError.PATH_EXISTS_ERR: msg + = 'Fil eller katalog finnes allerede'; gå i stykker; case FileError.TYPE_MISMATCH_ERR: msg + = 'Ugyldig filtype'; gå i stykker; standard: msg + = 'Ukjent feil'; gå i stykker; ; console.log (msg); ;

Filsystemobjektet du oppnår har en Navn (et unikt navn for filsystemet, tildelt av nettleseren) og rot eiendom som refererer til roten katalog av filsystemet. Dette er en DirectoryEntry objekt, og det kan ha nestede kataloger som er representert av DirectoryEntry objekter. Hver katalog i filsystemet kan inneholde filer representert av FileEntry objekter. De DirectoryEntry objekt definerer metoder for å skaffe seg DirectoryEntry og FileEntry objekter etter stinavn (de vil eventuelt opprette nye kataloger eller filer hvis du angir et navn som ikke eksisterer). DirectoryEntry definerer også a createReader () Fabrikkmetode som returnerer a DirectoryReader objekt for å oppgi innholdet i en katalog. De FileEntry Klassen definerer en metode for å skaffe Fil objekt (en Blob) som representerer innholdet i en fil. Du kan da bruke en Filereader motsette seg å lese filen. FileEntry definerer en annen metode for å returnere a Filewriter writer~~POS=HEADCOMP objekt som du kan bruke til å skrive innhold i en fil.

Phhew ... høres komplisert? Ikke bekymre deg. Alt blir tydeligere når vi går gjennom eksemplene nedenfor.


Trinn 2 - Arbeide med kataloger

Åpenbart, det første du trenger å lage i et filsystem er noen bøtter eller kataloger. Selv om rotkatalogen allerede eksisterer, vil du ikke plassere alle filene dine der. Kataloger er opprettet av DirectoryEntry gjenstand. I det følgende eksempelet oppretter vi en katalog som heter dokumenter, i rotkatalogen:

fs.root.getDirectory ('Documents', create: true, funksjon (dirEntry) alert ('Du har nettopp opprettet katalogen' + dirEntry.name + '.');, errorHandler);

De getDirectory () Metoden brukes både til å lese og lage kataloger. Som den første parameteren kan du passere enten et navn eller en bane som katalogen for å slå opp eller opprette. Vi setter det andre argumentet til ekte, fordi vi prøver å lage en katalog - ikke lese en eksisterende. Og til slutt legger vi til en tilbakekalling av feil.

Så langt så bra. Vi har en katalog; la oss legge til en underkatalog. Funksjonen er nøyaktig den samme med en forskjell: Vi endrer det første argumentet fra 'Dokumenter' til 'Dokumenter / Musikk'. Lett nok; men hva om du vil lage en undermappe, Himmel, med to foreldremapper, Bilder og Natur, inne i dokumenter mappe? Hvis du skriver 'Dokumenter / Images / Natur / Sky'for sti argumentet, vil du motta en feil, fordi du ikke kan opprette en katalog, når dens nærmeste forelder ikke eksisterer. En løsning for dette er å lage hver mappe en etter en: Bilder innsiden dokumenter, Natur innsiden Bilder, og så Himmel innsiden Natur. Men dette er en veldig langsom og ubeleilig prosess. Det er en bedre løsning: å opprette en funksjon som automatisk lager alle nødvendige mapper.

funksjon createDir (rootDir, mapper) rootDir.getDirectory (mapper [0], create: true, funksjon (dirEntry) if (folders.length) createDir (dirEntry, folders.slice (1)), Errorhandler); ; createDir (fs.root, 'Dokumenter / Bilder / Nature / Sky /'. split ('/'));

Med dette lille trikset er alt vi trenger å gjøre, å gi en full bane som representerer mappene som vi vil lage. Nå, den Himmel katalogen er opprettet, og du kan opprette andre filer eller kataloger i den.

Nå er det på tide å sjekke hva vi har i vårt filsystem. Vi lager en DirectoryReader objekt, og bruk readEntries () metode for å lese innholdet i katalogen.

fs.root.getDirectory ('Dokumenter', , funksjon (dirEntry) 
var dirReader = dirEntry.createReader (); dirReader.readEntries (funksjon (oppføringer)
for (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 ovenfor er isDirectory og isFile Egenskaper brukes for å oppnå en annen utgang for henholdsvis kataloger og filer. I tillegg bruker vi full vei eiendom for å få hele banen til oppføringen, i stedet for bare dens navn.

Det er to måter å fjerne a DirectoryEntry fra filsystemet: fjerne() og removeRecursively (). Den første fjerner bare en gitt katalog hvis den er tom. Ellers får du en feil.

fs.root.getDirectory ('Dokumenter / Musikk', , funksjon (dirEntry) dirEntry.remove (function () console.log ('Directory successfully removed.' ;;, errorHandler);, errorHandler);

Hvis Musikk mappen har filer innenfor den, da må du bruke den andre metoden, som rekursivt sletter katalogen og alt innholdet.

fs.root.getDirectory ('Documents / Music', , funksjon (dirEntry) dirEntry.removeRecursively (function () console.log ('Directory successufully removed.');, errorHandler);, errorHandler);

Trinn 3 - Arbeide med filer

Nå som vi vet hvordan du lager kataloger, er det på tide å fylle dem med filer!

Følgende eksempel oppretter en tom test.txt i rotkatalogen:

fs.root.getFile ('test.txt', opprett: sant, eksklusivt: true, funksjon (fileEntry) alert ('En fil' + fileEntry.name + 'ble opprettet med suksess.');, errorHandler) ;

Det første argumentet til getFile () kan være en absolutt eller relativ vei, men den må være gyldig. For eksempel er det en feil å forsøke å opprette en fil, når dens nærmeste forelder ikke eksisterer. Det andre argumentet er et objekt bokstavelig, som beskriver funksjonens oppførsel hvis filen ikke eksisterer. I dette eksemplet, skape: sant lager filen hvis den ikke eksisterer og kaster en feil hvis den gjør det (eksklusivt: sant). Ellers, hvis opprett: false, filen hentes bare og returneres.

Å ha en tom fil er ikke veldig nyttig, skjønt; så la oss legge til noe innhold inni. Vi kan bruke Filewriter writer~~POS=HEADCOMP protester mot dette.

fs.root.getFile ('test.txt', create: false, funksjon (fileEntry) fileEntry.createWriter (funksjon (fileWriter) window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder; var bb = ny BlobBuilder (); bb.append ('Filsystemet API er kjempebra!'); fileWriter.write (bb.getBlob ('text / plain')), errorHandler);, errorHandler);

Ovenfor henter vi test.txt fil, og opprett en Filewriter writer~~POS=HEADCOMP protestere mot det. Vi legger deretter til innhold ved å opprette en ny BlobBuilder objekt og bruk skrive() Metode av Filewriter writer~~POS=HEADCOMP.

ringe getFile () bare henter a FileEntry. Det returnerer ikke innholdet i filen. Så, hvis vi vil lese innholdet i filen, må vi bruke Fil objekt og Filereader gjenstand.

fs.root.getFile ('test.txt', , funksjon (fileEntry) fileEntry.file (funksjon (fil) var leser = ny FileReader (); reader.onloadend = funksjon (e) alert resultat);; leser.readAsText (fil);, errorHandler);, errorHandler);

Vi har skrevet noe innhold til vår fil, men hva om ønske om å legge til flere på et senere tidspunkt? For å legge til data i en eksisterende fil, vil Filewriter writer~~POS=HEADCOMP brukes igjen. Vi kan reposisjonere forfatteren til slutten av filen, ved hjelp av søke() metode. søke aksepterer en byteforskyvning som et argument, og setter filforfatterens posisjon til den forskyvningen.

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

For å fjerne en fil fra filsystemet, ring bare entry.remove (). Det første argumentet for denne metoden er en nullparameter tilbakeringingsfunksjon, som kalles når filen slettes. Den andre er en valgfri feil tilbakeringing hvis det oppstår feil.

fs.root.getFile ('test.txt', create: false, funksjon (fileEntry) fileEntry.remove (function () console.log ('File successufully removed.';, errorHandler); Errorhandler);

Trinn 4 - Manipulere filer og kataloger

FileEntry og DirectoryEntry Del de samme API-metodene for kopiering, flytting og omdøping av oppføringer. Det finnes to metoder du kan bruke for disse operasjonene: kopier til() og flytte til(). De begge aksepterer nøyaktig samme parametere:

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

Den første parameteren er den overordnede mappen for å flytte / kopiere oppføringen til. Den andre er et valgfritt nytt navn for å gi den flyttede / kopierte oppføringen, som faktisk er nødvendig når du kopierer en oppføring i samme mappe; ellers får du en feil. Den tredje og fjerde parametere ble forklart tidligere.

La oss se på noen enkle eksempler. I det følgende kopierer vi filen test.txt fra rot til dokumenter katalog.

funksjons kopi (currDir, srcEntry, destDir) currDir.getFile (srcEntry, , funksjon (fileEntry) currDir.getDirectory (destDir, , funksjon (dirEntry) fileEntry.copyTo (dirEntry);, errorHandler); , errorHandler);  kopi (fs.root, 'test.txt', 'Documents /');

Dette neste eksempelet beveger seg test.txt til dokumenter, i stedet for å kopiere den:

funksjonen flytte (currDir, srcEntry, dirName) currDir.getFile (srcEntry, , funksjon (fileEntry) currDir.getDirectory (dirName, , funksjon (dirEntry) fileEntry.moveTo (dirEntry);, errorHandler); , errorHandler);  flytte (fs.root, 'test.txt', 'Documents /');

Følgende eksempel omdøper test.txt til text.txt:

funksjonen omdøpe (currDir, srcEntry, newName) currDir.getFile (srcEntry, , funksjon (fileEntry) fileEntry.moveTo (currDir, newName);, errorHandler);  endre navn (fs.root, 'test.txt', 'text.txt');

Lære mer

I denne innledende opplæringen har vi bare skrapet overflaten på de forskjellige filsystemgrensesnittene. Hvis du vil lære mer og grave dypere inn i Filesystem API, bør du se W3C spesifikasjonsspesifikasjonene:

  • Fil API: Kataloger og system
  • Fil-API: Skribent
  • Fil-API

Nå som du har en grunnleggende forståelse av hva Filsystem API er, og hvordan det kan brukes, bør det være betydelig lettere å forstå API-dokumentasjonen, noe som kan være litt forvirrende ved første blikk.


Konklusjon

Filsystemet API er en kraftig og brukervennlig teknologi som gir webutviklere en hel del nye muligheter når man bygger webapplikasjoner. Admittedly, det er fortsatt ganske nytt og ikke mye støttet av alle de store nettleserne, men dette vil sikkert endre seg i fremtiden. Du kan like godt få en start!