Toying cu API-ul sistemului de fișiere HTML5

HTML5 ne oferă o întreagă recoltă de noi posibilități, cum ar fi desenul cu pânză, implementarea multimedia cu API-urile audio și video și așa mai departe. Unul dintre aceste instrumente, care este încă relativ nou, este API-ul File System. Ne dă acces la o secțiune de tip "sandboxed" a sistemului de fișiere local al utilizatorului, umplând astfel și mai mult decalajul dintre aplicațiile desktop și cele web! În tutorialul de astăzi, vom trece prin elementele de bază ale acestui API nou și interesant, explorând cele mai frecvente sarcini ale sistemului de fișiere. Să începem!


Introducere

Nu mai trebuie să descărcați și să instalați un anumit software pentru ao folosi. Pur și simplu un browser web și o conexiune la internet ne oferă posibilitatea de a folosi orice aplicație web, oricând, oriunde și pe orice platformă.

Pe scurt, aplicațiile web sunt reci; dar, în comparație cu aplicațiile desktop, acestea au încă o slăbiciune semnificativă: nu au o modalitate de a interacționa și de a organiza datele într-o ierarhie structurată a folderelor - un sistem de fișiere real. Din fericire, cu noul API de fișiere, acest lucru poate fi schimbat. Acest API oferă aplicațiilor web acces controlat la un sistem de fișiere privat "sandbox", în care pot scrie și citi fișiere, creează și afișează directoare și așa mai departe. Deși în momentul acestei scrieri numai browserul Chrome Google acceptă implementarea "completă" a API-ului Filesystem, merită încă să fie studiată ca o formă puternică și convenabilă de stocare locală.

API-ul Filesystem vine în două versiuni diferite. API-ul asincron, care este util pentru aplicații normale, și API-ul sincron, rezervat pentru utilizarea cu lucrătorii web. În scopul acestui tutorial, vom explora exclusiv versiunea asincronă a API.


Pasul 1 - Noțiuni de bază

Primul pas este să obțineți accesul la sistemul de fișiere HTML5 solicitând a LocalFile Obiect sistem, folosind window.requestFileSystem () metoda globală:

window.requestFileSystem (tip, dimensiune, succesCallback, opt_errorCallback)

Nu există nicio modalitate pentru ca o aplicație web să "izbucnească" dincolo de directorul rădăcină local.

Ca primii doi parametri, specificați durata de viață și dimensiunea sistemului de fișiere dorit. A PERSISTENT sistemul de fișiere este potrivit pentru aplicațiile web care doresc să stocheze permanent datele utilizatorilor. Browserul nu îl va șterge, cu excepția solicitării explicite a utilizatorului. A TEMPORAR sistemul de fișiere este potrivit pentru aplicațiile web care doresc să cacheze datele, dar poate funcționa în continuare dacă browserul web șterge sistemul de fișiere. Mărimea sistemului de fișiere este specificată în octeți și ar trebui să fie o limită superioară rezonabilă a cantității de date pe care trebuie să le stocați.

Al treilea parametru este o funcție de apel invers care este declanșată atunci când agentul utilizatorului oferă cu succes un sistem de fișiere. Argumentul său este a Sistemul de fișiere obiect. Și, în sfârșit, putem adăuga o funcție opțională de apel invers, care se numește atunci când apare o eroare sau dacă cererea pentru un sistem de fișiere este respinsă. Argumentul său este a FileError obiect. Deși acest parametru este opțional, este întotdeauna o idee bună să prindeți erori pentru utilizatori, deoarece există o serie de locuri în care lucrurile pot merge prost.

Sistemul de fișiere obținut cu aceste funcții depinde de originea documentului care conține documentul. Toate documentele sau aplicațiile web de aceeași origine (gazdă, port și protocol) partajează un sistem de fișiere. Două documente sau aplicații de origine diferită au sisteme de fișiere complet separate și disjuncte. Un sistem de fișiere este limitat la o singură aplicație și nu poate accesa datele stocate de o altă aplicație. Este, de asemenea, izolat de restul fișierelor de pe hard disk-ul utilizatorului, ceea ce este un lucru bun: nu există nicio modalitate pentru ca o aplicație web să "izbucnească" dincolo de directorul rădăcină local sau să acceseze în alt mod fișiere arbitrare.

Să examinăm un exemplu:

window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; window.requestFileSystem (fereastră.TEMPORARĂ, 5 * 1024 * 1024, initFS, errorHandler); funcția initFS (fs) alert ("Bine ati venit la sistemul de fișiere! Este showtime :)"); // Doar pentru a verifica dacă totul este OK :) // puneți funcțiile pe care le veți afla mai jos aici funcția errorHandler () console.log ('A apărut o eroare'); 

Acest lucru creează un sistem de fișiere temporar cu spațiu de stocare de 5 MB. Acesta oferă apoi o funcție de apel de succes, pe care o vom folosi pentru a opera sistemul nostru de fișiere. Și, bineînțeles, este adăugat și un handler de eroare - doar în cazul în care ceva nu merge bine. Aici ErrorHandler () funcția este prea generică. Deci, dacă doriți, puteți crea o versiune ușor optimizată, care oferă cititorului un mesaj de eroare mai descriptiv:

function errorHandler (err) var msg = 'A apărut o eroare:'; switch (err.code) caz FileError.NOT_FOUND_ERR: msg + = 'Fișierul sau directorul nu a fost găsit'; pauză; caz FileError.NOT_READABLE_ERR: msg + = 'Fișier sau director care nu poate fi citit'; pauză; caz FileError.PATH_EXISTS_ERR: msg + = 'Fișierul sau directorul există deja'; pauză; caz FileError.TYPE_MISMATCH_ERR: msg + = 'Tip de fișier nevalid'; pauză; implicit: msg + = 'Eroare necunoscută'; pauză; ; console.log (msg); ;

Obiectul sistemului de fișiere pe care îl obțineți are a Nume (un nume unic pentru sistemul de fișiere atribuit de browser) și rădăcină proprietate care se referă la directorul rădăcină al sistemului de fișiere. Acesta este un DirectoryEntry obiect și poate avea directoare imbricate care sunt ele însele reprezentate DirectoryEntry obiecte. Fiecare director din sistemul de fișiere poate conține fișiere reprezentate de FileEntry obiecte. DirectoryEntry obiect definește metodele de obținere DirectoryEntry și FileEntry obiecte după numele căii (acestea vor crea, opțional, directoare sau fișiere noi dacă specificați un nume care nu există). DirectoryEntry definește și a createReader () metoda fabricii care returnează a DirectoryReader obiect pentru listarea conținutului unui director. FileEntry clasa definește o metodă pentru obținerea Fişier obiect (un Blob) care reprezintă conținutul unui fișier. Puteți folosi a FileReader obiect pentru a citi fișierul. FileEntry definește o altă metodă de returnare a FileWriter obiect pe care îl puteți utiliza pentru a scrie conținut într-un fișier.

Phhew ... sună complicat? Nu-ți face griji. Totul va deveni mai clar pe măsură ce progresăm prin exemplele de mai jos.


Pasul 2 - Lucrul cu directoare

Evident, primul lucru pe care trebuie să-l creați într-un sistem de fișiere este unele găleți sau directoare. Deși directorul rădăcină există deja, nu doriți să plasați toate fișierele dvs. acolo. Directoarele sunt create de către DirectoryEntry obiect. În exemplul următor, vom crea un director, numit Documente, în directorul rădăcină:

fs.root.getDirectory ('Documents', create: true, function (dirEntry) alert ('Ati creat directorul' + dirEntry.name + ';), errorHandler);

getDirectory () metoda este utilizată atât pentru a citi, cât și pentru a crea directoare. Ca primul parametru, puteți trece fie un nume, fie o cale ca director pentru a căuta sau a crea. Am setat al doilea argument la Adevărat, pentru că încercăm să creăm un director - să nu citim unul existent. Și, la final, adăugăm un apel de eroare.

Până acum, bine. Avem un director; să adăugăm acum un subdirector. Funcția este exact aceeași cu o diferență: schimbăm primul argument din "Documente" în "Documente / Muzică". Destul de usor; dar dacă doriți să creați un subfolder, Cer, cu două dosare părinte, Imagini și Natură, în interiorul Documente pliant? Dacă tastați "Documente / Imagini / Natură / Sky"pentru argumentul căii, veți primi o eroare, deoarece nu puteți crea un director, atunci când părintele său imediat nu există. O soluție pentru aceasta este de a crea fiecare dosar unul câte unul: Imagini interior Documente, Natură interior Imagini, și apoi Cer interior Natură. Dar acesta este un proces foarte lent și incomod. Există o soluție mai bună: să creați o funcție care să creeze automat toate folderele necesare.

(dirEntry, folders.slice (1));, ErrorHandler); ; createDir (fi.root, "Documente / Imagini / Natura / Sky /" split ('/'));

Cu acest truc mic, tot ce trebuie să facem este să oferim o cale completă reprezentând dosarele pe care vrem să le creăm. Acum Cer directorul este creat cu succes, și puteți crea alte fișiere sau directoare în cadrul acestuia.

Acum este momentul să verificăm ce avem în sistemul nostru de fișiere. Vom crea o DirectoryReader obiect și utilizați readEntries () pentru a citi conținutul directorului.

fs.root.getDirectory ("Documente", , funcție (dirEntry) 
var dirReader = dirEntry.createReader (); dirReader.readEntries (funcție (intrări)
pentru (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);

În codul de mai sus, isDirectory și isFile proprietățile sunt utilizate pentru a obține o ieșire diferită pentru directoare și fișiere, respectiv. În plus, folosim fullpath proprietate pentru a obține calea completă a intrării, în loc de numele său numai.

Există două moduri de a elimina a DirectoryEntry din sistemul de fișiere: elimina() și removeRecursively (). Primul elimină un director dat numai dacă este gol. În caz contrar, veți primi o eroare.

fs.root.getDirectory ('Documente / Muzică', , funcția (dirEntry) dirEntry.remove (funcția () console.log ('Directorul a fost eliminat cu succes';), errorHandler);

În cazul în care Muzică folderul are fișiere în el, atunci trebuie să utilizați a doua metodă, care șterge recursiv directorul și tot conținutul acestuia.

fs.root.getDirectory ('Documente / Muzică', , funcția (dirEntry) dirEntry.removeRecursively (funcția () console.log ('Directory succesufully removed');

Pasul 3 - Lucrul cu fișierele

Acum, că știm cum să creați directoare, este timpul să le populam cu fișiere!

Următorul exemplu creează un spațiu gol test.txt în directorul rădăcină:

fs.root.getFile ('test.txt', create: true, exclusive: true, funcția (fileEntry) alert ('A file' + fileEntry.name + ;

Primul argument pentru ia fisierul() poate fi o cale absolută sau relativă, dar trebuie să fie validă. De exemplu, este o eroare în încercarea de a crea un fișier, atunci când părintele său imediat nu există. Al doilea argument este un obiect literal, care descrie comportamentul funcției dacă fișierul nu există. În acest exemplu, creați: adevărat creează fișierul dacă nu există și aruncă o eroare dacă o face (exclusiv: adevărat). În caz contrar, dacă creați: false, fișierul este pur și simplu preluat și returnat.

Având un fișier gol nu este foarte util, totuși; deci să adăugăm conținut înăuntru. Putem folosi FileWriter obiect pentru aceasta.

fs.root.getFile ('test.txt', create: false, funcția (fileEntry) fileEntry.createWriter (funcția (fileWriter) window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder; var bb = noul BlobBuilder (); bb.append ('API-ul sistemului de fișiere este minunat!'); fileWriter.write (bb.getBlob ('text / simplu');), errorHandler;), errorHandler);

Deasupra, vom prelua test.txt fișier și creați un FileWriter obiect pentru el. Apoi adăugăm conținut la acesta creând un nou BlobBuilder obiect și folosind scrie() Metodă de FileWriter.

apel ia fisierul() recuperează doar a FileEntry. Nu returnează conținutul fișierului. Deci, dacă vrem să citim conținutul fișierului, trebuie să îl folosim Fişier obiect și FileReader obiect.

fs.root.getFile ('test.txt', , funcția (fileEntry) fileEntry.file (funcția (fișierul) var reader = new FileReader (); reader.onloadend = function (e) alert. rezultatul);; reader.readAsText (fișier);, errorHandler);, errorHandler);

Am scris ceva conținut în fișierul nostru, dar dacă doriți să adăugați mai multe la o dată ulterioară? Pentru a adăuga date la un fișier existent, FileWriter este folosit din nou. Putem repoziționa scriitorul la sfârșitul fișierului, folosind căuta() metodă. căuta acceptă un decalaj de octeți ca argument și reglează poziția scriitorului de fișiere la acel offset.

fs.root.getFile ('test.txt', create: false, funcția (fileEntry) fileEntry.createWriter (funcția (fileWriter) fileWriter.seek (fileWriter.length); window.BlobBuilder = window.BlobBuilder || fereastra.WebKitBlobBuilder; var bb = nou BlobBuilder (); bb.append ('Da, este!'); fileWriter.write (bb.getBlob ('text / simplu')); errorHandler; ;

Pentru a elimina un fișier din sistemul de fișiere, pur și simplu apelați entry.remove (). Primul argument pentru această metodă este o funcție de returnare a apelului parametrului zero, care se numește atunci când fișierul este șters cu succes. Al doilea este un apel de eroare opțional în cazul în care apar erori.

fs.root.getFile ('test.txt', create: false, functie (fileEntry) fileEntry.remove (function () console.log ErrorHandler);

Pasul 4 - Manipularea fișierelor și a directoarelor

FileEntry și DirectoryEntry împărtășesc aceleași metode API pentru copierea, mutarea și redenumirea intrărilor. Există două metode pe care le puteți utiliza pentru aceste operații: copiaza in() și MoveTo (). Ambele acceptă exact aceiași parametri:

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

Primul parametru este dosarul părinte pentru a muta / copia intrarea. Al doilea este un nume nou opțional pentru a da intrarea mutată / copiată, care este de fapt necesară atunci când copiați o intrare în același folder; altfel veți primi o eroare. Al treilea și al patrulea parametru au fost explicați anterior.

Să revedem câteva exemple simple. În următorul, vom copia fișierul test.txt de la rădăcină la Documente director.

(currDir, srcEntry, destDir) currDir.getFile (srcEntry, , functie (fileEntry) currDir.getDirectory (destDir, , functie (dirEntry) fileEntry.copyTo (dirEntry); , errorHandler);  copie (fi.root, 'test.txt', 'Documente /');

Următorul exemplu se mută test.txt la Documente, în loc să o copiați:

funcția (currDir, srcEntry, dirName) currDir.getFile (srcEntry, , funcția (fileEntry) currDir.getDirectory (dirName, , funcția (dirEntry) fileEntry.moveTo (dirEntry); , errorHandler);  mutați (fs.root, 'test.txt', 'Documente /');

Următorul exemplu redenumește test.txt la text.txt:

funcția redenumire (currDir, srcEntry, newName) currDir.getFile (srcEntry, , funcția (fileEntry) fileEntry.moveTo (currDir, newName);, errorHandler);  redenumiți (fs.root, 'test.txt', 'text.txt');

Aflați mai multe

În acest tutorial introductiv, am zgâriat numai suprafața diferitelor interfețe de sistem de fișiere. Dacă doriți să aflați mai multe și să explorați mai adânc în API-ul Filesystem, trebuie să consultați specificațiile W3C:

  • API pentru fișiere: Directoare și sistem
  • API pentru fișiere: Writer
  • API pentru fișiere

Acum că aveți o înțelegere de bază a ceea ce este API-ul Filesystem și cum poate fi folosit, ar trebui să fie mult mai ușor de înțeles documentația API, ceea ce poate fi puțin confuz la prima vedere.


Concluzie

API-ul Filesystem este o tehnologie puternică și ușor de folosit, care oferă dezvoltatorilor web o întreagă recoltă de noi posibilități atunci când construiesc aplicații web. Desigur, este încă destul de nou și nu este acceptat pe scară largă de toate browserele majore, dar acest lucru se va schimba cu siguranță în viitor. S-ar putea să începi bine!

Cod