Jouant avec l'API HTML5 du système de fichiers

HTML5 nous offre une foule de nouvelles possibilités, telles que le dessin avec canvas, l'implémentation multimédia avec les API audio et vidéo, etc. L’un de ces outils, qui est encore relativement nouveau, est l’API du système de fichiers. Il nous donne accès à une section en sandbox du système de fichiers local de l'utilisateur, comblant ainsi le fossé entre les applications de bureau et les applications Web! Dans le didacticiel d'aujourd'hui, nous allons passer en revue les bases de cette nouvelle et passionnante API, en explorant les tâches les plus courantes du système de fichiers. Commençons!


introduction

Nous n'avons plus besoin de télécharger et d'installer un logiciel pour pouvoir l'utiliser. Un simple navigateur Web et une connexion Internet nous permettent d'utiliser n'importe quelle application Web, à tout moment, n'importe où et sur n'importe quelle plateforme..

En bref, les applications Web sont cool; mais, comparés aux applications de bureau, ils ont toujours une faiblesse importante: ils ne disposent pas d’un moyen permettant d’interagir et d’organiser les données dans une hiérarchie structurée de dossiers - un véritable système de fichiers. Heureusement, avec la nouvelle API de système de fichiers, cela peut être modifié. Cette API donne aux applications Web un accès contrôlé à un système de fichiers local privé "sandbox", dans lequel elles peuvent écrire et lire des fichiers, créer et répertorier des répertoires, etc. Bien que, au moment de la rédaction de ce document, seul le navigateur Chrome de Google prenne en charge l’implémentation "complète" de l’API du système de fichiers, il mérite toujours d’être étudié comme une forme puissante et pratique de stockage local..

L’API du système de fichiers est disponible en deux versions différentes. L'API asynchrone, utile pour les applications normales, et l'API synchrone, réservée aux travailleurs Web. Pour les besoins de ce tutoriel, nous explorerons exclusivement la version asynchrone de l'API..


Étape 1 - Mise en route

Votre première étape consiste à accéder au système de fichiers HTML5 en demandant une LocalFile Objet système, en utilisant le window.requestFileSystem () méthode globale:

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

Il n'y a aucun moyen pour une application Web de "sortir" du répertoire racine local.

En tant que les deux premiers paramètres, vous spécifiez la durée de vie et la taille du système de fichiers souhaité. UNE PERSISTANT Le système de fichiers convient aux applications Web qui souhaitent stocker des données utilisateur de manière permanente. Le navigateur ne le supprimera pas, sauf à la demande explicite de l'utilisateur. UNE TEMPORAIRE Le système de fichiers convient aux applications Web qui souhaitent mettre en cache des données, mais peut toujours fonctionner si le navigateur Web supprime le système de fichiers. La taille du système de fichiers est spécifiée en octets et doit constituer une limite supérieure raisonnable de la quantité de données que vous devez stocker..

Le troisième paramètre est une fonction de rappel déclenchée lorsque l'agent utilisateur fournit avec succès un système de fichiers. Son argument est un Système de fichiers objet. Et, enfin, nous pouvons ajouter une fonction de rappel facultative, appelée en cas d'erreur, ou lorsque la demande de système de fichiers est refusée. Son argument est un Erreur de fichier objet. Bien que ce paramètre soit facultatif, il est toujours judicieux d’attraper les erreurs pour les utilisateurs, car il existe plusieurs endroits où les choses peuvent mal tourner..

Le système de fichiers obtenu avec ces fonctions dépend de l'origine du document contenant. Tous les documents ou applications Web de la même origine (hôte, port et protocole) partagent un système de fichiers. Deux documents ou applications d'origines différentes ont des systèmes de fichiers complètement distincts et disjoints. Un système de fichiers est limité à une seule application et ne peut pas accéder aux données stockées d'une autre application. Elle est également isolée du reste des fichiers du disque dur de l'utilisateur, ce qui est une bonne chose: aucune application Web ne peut "sortir" du répertoire racine local ou accéder autrement à des fichiers arbitraires..

Passons en revue un exemple:

window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; window.requestFileSystem (window.TEMPORARY, 5 * 1024 * 1024, initFS, errorHandler); function initFS (fs) alert ("Bienvenue dans le système de fichiers! C'est showtime :)"); // Juste pour vérifier si tout va bien :) // placez les fonctions que vous allez apprendre ci-dessous function errorHandler () console.log ('Une erreur est survenue'); 

Cela crée un système de fichiers temporaire avec 5 Mo de stockage. Il fournit ensuite une fonction de rappel de réussite, que nous utiliserons pour faire fonctionner notre système de fichiers. Et, bien sûr, un gestionnaire d'erreurs est également ajouté - juste au cas où quelque chose se passe mal. Ici le errorHandler () la fonction est trop générique. Donc, si vous le souhaitez, vous pouvez créer une version légèrement optimisée, qui donne au lecteur un message d'erreur plus descriptif:

function errorHandler (err) var msg = 'Une erreur est survenue:'; switch (err.code) case FileError.NOT_FOUND_ERR: msg + = 'Fichier ou répertoire non trouvé'; Pause; case FileError.NOT_READABLE_ERR: msg + = 'Fichier ou répertoire non lisible'; Pause; case FileError.PATH_EXISTS_ERR: msg + = 'Le fichier ou le répertoire existe déjà'; Pause; case FileError.TYPE_MISMATCH_ERR: msg + = 'Type de fichier non valide'; Pause; défaut: msg + = 'Erreur inconnue'; Pause; ; console.log (msg); ;

L'objet du système de fichiers que vous obtenez a prénom (un nom unique pour le système de fichiers, attribué par le navigateur) et racine propriété qui fait référence au répertoire racine du système de fichiers. C'est un AnnuaireEntrée objet, et il peut avoir des répertoires imbriqués qui sont eux-mêmes représentés par AnnuaireEntrée objets. Chaque répertoire du système de fichiers peut contenir des fichiers, représentés par FileEntry objets. le AnnuaireEntrée objet définit les méthodes d'obtention AnnuaireEntrée et FileEntry objets par chemin (ils créeront éventuellement de nouveaux répertoires ou fichiers si vous spécifiez un nom qui n'existe pas). AnnuaireEntrée définit également un createReader () méthode d'usine qui retourne un RépertoireReader objet pour lister le contenu d'un répertoire. le FileEntry classe définit une méthode pour obtenir le Fichier objet (un blob) qui représente le contenu d'un fichier. Vous pouvez alors utiliser un FileReader objet pour lire le fichier. FileEntry définit une autre méthode pour renvoyer un FileWriter objet que vous pouvez utiliser pour écrire du contenu dans un fichier.

Phhew… semble compliqué? Ne t'inquiète pas. Tout deviendra plus clair au fil des exemples ci-dessous..


Étape 2 - Travailler avec des répertoires

De toute évidence, la première chose à créer dans un système de fichiers est constituée de compartiments ou de répertoires. Bien que le répertoire racine existe déjà, vous ne voulez pas y placer tous vos fichiers. Les répertoires sont créés par le AnnuaireEntrée objet. Dans l'exemple suivant, nous créons un répertoire, appelé Les documents, dans le répertoire racine:

fs.root.getDirectory ('Documents', create: true, fonction (dirEntry) alert ('Vous venez de créer le répertoire' + dirEntry.name + '.');, errorHandler);

le getDirectory () La méthode est utilisée à la fois pour lire et créer des répertoires. En tant que premier paramètre, vous pouvez transmettre un nom ou un chemin en tant que répertoire à rechercher ou à créer. Nous plaçons le deuxième argument à vrai, parce que nous essayons de créer un répertoire - ne pas lire un répertoire existant. Et à la fin, nous ajoutons un rappel d'erreur.

Jusqu'ici tout va bien. Nous avons un annuaire; ajoutons maintenant un sous-répertoire. La fonction est exactement la même chose avec une différence: nous changeons le premier argument de 'Documents' à 'Documents / Music'. Assez facile; mais si vous voulez créer un sous-dossier, Ciel, avec deux dossiers parents, Images et La nature, à l'intérieur de Les documents dossier? Si vous tapez 'Documents / Images / Nature / Ciel'pour l'argument path, vous recevrez une erreur, car vous ne pouvez pas créer de répertoire, lorsque son parent immédiat n'existe pas. Une solution pour cela consiste à créer chaque dossier un à un: Images à l'intérieur Les documents, La nature à l'intérieur Images, et alors Ciel à l'intérieur La nature. Mais il s’agit d’un processus très lent et peu pratique. Il existe une meilleure solution: créer une fonction qui créera automatiquement tous les dossiers nécessaires..

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

Avec cette petite astuce, tout ce que nous avons à faire est de fournir un chemin complet représentant les dossiers que nous voulons créer. Maintenant le Ciel le répertoire est créé avec succès et vous pouvez créer d’autres fichiers ou répertoires.

Il est maintenant temps de vérifier ce que nous avons dans notre système de fichiers. Nous allons créer un RépertoireReader objet, et utilisez le readEntries () méthode pour lire le contenu du répertoire.

fs.root.getDirectory ('Documents', , fonction (dirEntry) 
var dirReader = dirEntry.createReader (); dirReader.readEntries (fonction (entrées)
pour (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);

Dans le code ci-dessus, le isDirectory et isFile les propriétés sont utilisées pour obtenir une sortie différente pour les répertoires et les fichiers, respectivement. De plus, nous utilisons le chemin complet propriété afin d'obtenir le chemin d'accès complet de l'entrée, au lieu de son nom uniquement.

Il y a deux façons de supprimer un AnnuaireEntrée depuis le système de fichiers: retirer() et removeRecursively (). Le premier ne supprime un répertoire donné que s'il est vide. Sinon, vous recevrez une erreur.

fs.root.getDirectory ('Documents / Musique', , fonction (dirEntry) dirEntry.remove (function () console.log ('Répertoire supprimé.');,, errorHandler);, errorHandler);

Si la La musique dossier contient des fichiers, vous devez utiliser la seconde méthode, qui supprime de manière récursive le répertoire et tout son contenu.

fs.root.getDirectory ('Documents / Musique', , fonction (dirEntry) dirEntry.removeRecursively (function () console.log ('Répertoire supprimé.');, errorHandler);, errorHandler);

Étape 3 - Travailler avec des fichiers

Maintenant que nous savons créer des répertoires, il est temps de les remplir avec des fichiers!

L'exemple suivant crée un vide test.txt dans le répertoire racine:

fs.root.getFile ('test.txt', créer: true, exclusif: true, fonction (fileEntry) alert ('Un fichier' + fichierEntrée.nom + 'a été créé avec succès.');, errorHandler) ;

Le premier argument à getFile () peut être un chemin absolu ou relatif, mais il doit être valide. Par exemple, tenter de créer un fichier est une erreur lorsque son parent immédiat n'existe pas. Le deuxième argument est un littéral d'objet, décrivant le comportement de la fonction si le fichier n'existe pas. Dans cet exemple, créer: vrai crée le fichier s’il n’existe pas et génère une erreur s’il existe (exclusif: vrai). Sinon, si créer: faux, le fichier est simplement récupéré et renvoyé.

Avoir un fichier vide n'est pas très utile, cependant; ajoutons donc du contenu à l'intérieur. Nous pouvons utiliser le FileWriter objet pour cela.

fs.root.getFile ('test.txt', create: false, fonction (fileEntry) fileEntry.createWriter (fonction (fileWriter) window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder; var bb = new BlobBuilder; (); bb.append ('L'API du système de fichiers est génial!'); fileWriter.write (bb.getBlob ('text / plain'));, errorHandler);, errorHandler);

Ci-dessus, nous récupérons le test.txt fichier et créer un FileWriter objet pour cela. Nous y ajoutons ensuite du contenu en créant un nouveau BlobBuilder objet et en utilisant le écrire() méthode de FileWriter.

Appel getFile () récupère seulement un FileEntry. Il ne renvoie pas le contenu du fichier. Donc, si nous voulons lire le contenu du fichier, nous devons utiliser le Fichier objet et le FileReader objet.

fs.root.getFile ('test.txt', , function (fileEntry) fileEntry.file (function (fichier) var reader = new FileReader (); reader.onloadend = function (e) alert (this. résultat);; reader.readAsText (file);, errorHandler);, errorHandler);

Nous avons écrit du contenu dans notre fichier, mais que se passe-t-il si vous souhaitez en ajouter davantage ultérieurement? Pour ajouter des données à un fichier existant, le FileWriter est utilisé encore une fois. Nous pouvons repositionner le graveur à la fin du fichier, en utilisant le chercher() méthode. chercher accepte un décalage d'octet en tant qu'argument et définit la position de l'auteur du fichier sur ce décalage.

fs.root.getFile ('test.txt', create: false, fonction (fileEntry) fileEntry.createWriter (fonction (fileWriter) fileWriter.seek (fileWriter.length); window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder; var bb = new BlobBuilder (); bb.append ('Oui, c'est!'); fileWriter.write (bb.getBlob ('text / plain'));, errorHandler);, errorHandler) ;

Pour supprimer un fichier du système de fichiers, appelez simplement entry.remove (). Le premier argument de cette méthode est une fonction de rappel à paramètre zéro, appelée lorsque le fichier est supprimé avec succès. La seconde est un rappel d'erreur optionnel si des erreurs se produisent.

fs.root.getFile ('test.txt', create: false, fonction (fileEntry) fileEntry.remove (function () console.log ('Fichier supprimé avec succès.');, errorHandler);, errorHandler);

Étape 4 - Manipulation des fichiers et des répertoires

FileEntry et AnnuaireEntrée partager les mêmes méthodes d'API pour copier, déplacer et renommer des entrées. Vous pouvez utiliser deux méthodes pour ces opérations: copier() et déménager à(). Ils acceptent tous les deux exactement les mêmes paramètres:

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

Le premier paramètre est le dossier parent dans lequel déplacer / copier l'entrée. Le second est un nouveau nom facultatif pour donner l’entrée déplacée / copiée, ce qui est en fait requis lorsque vous copiez une entrée dans le même dossier; sinon vous obtiendrez une erreur. Les troisième et quatrième paramètres ont été expliqués précédemment.

Passons en revue quelques exemples simples. Dans la suivante, nous copions le fichier test.txt du racine au Les documents annuaire.

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

Cet exemple suivant se déplace test.txt à Les documents, au lieu de le copier:

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

L'exemple suivant renomme test.txt à text.txt:

renommer la fonction (currDir, srcEntry, newName) currDir.getFile (srcEntry, , fonction (fileEntry) fileEntry.moveTo (currDir, newName);, errorHandler);  renommer (fs.root, 'test.txt', 'text.txt');

Apprendre encore plus

Dans ce tutoriel d'introduction, nous n'avons fait qu'effleurer la surface des différentes interfaces de système de fichiers. Si vous souhaitez en savoir plus et approfondir vos connaissances dans l'API du système de fichiers, vous devez vous reporter aux spécifications du W3C:

  • API de fichier: Répertoires et système
  • API de fichier: Writer
  • API de fichier

Maintenant que vous avez une compréhension de base de l’API de système de fichiers et de la façon dont elle peut être utilisée, il devrait être beaucoup plus facile de comprendre la documentation de l’API, ce qui peut être un peu déroutant à première vue..


Conclusion

L’API de système de fichiers est une technologie puissante et facile à utiliser, qui offre aux développeurs Web de nombreuses possibilités nouvelles lors de la création d’applications Web. Certes, il est encore assez récent et n’est pas largement supporté par tous les principaux navigateurs, mais cela changera certainement dans le futur. Vous pourriez aussi bien avoir une longueur d'avance!