API Storage

Presque tous les aspects du développement d'applications impliquent l'envoi ou la réception de données. À partir des bases, vous devez utiliser un framework MVC pour concevoir et implémenter votre application de sorte que les données soient complètement distinctes de la vue de l'application sur ces données (voir Architecture MVC).

Vous devez également réfléchir à la manière dont les données sont gérées lorsque votre application est hors connexion (voir la section Hors connexion). Ce document présente brièvement les options de stockage permettant d'envoyer, de recevoir et d'enregistrer des données en local. Le reste du document explique comment utiliser les API File System et Sync File System de Chrome (voir également API fileSystem et API syncFileSystem).

Options de stockage

Les applications empaquetées utilisent de nombreux mécanismes différents pour envoyer et recevoir des données. Pour les données externes (ressources, pages Web), vous devez connaître la Content Security Policy (CSP). Comme pour les extensions Chrome, vous pouvez utiliser des requêtes XMLHttpRequests multi-origines pour communiquer avec des serveurs distants. Vous pouvez également isoler les pages externes afin que le reste de votre application soit sécurisé (voir Intégrer des pages Web externes).

Lorsque vous enregistrez des données localement, vous pouvez utiliser l'API Chrome Storage pour enregistrer de petites quantités de données de chaîne et IndexedDB pour enregistrer des données structurées. Avec IndexedDB, vous pouvez conserver des objets JavaScript dans un magasin d'objets et utiliser les index du magasin pour interroger les données (pour en savoir plus, consultez le tutoriel de liste de tâches simple de HTML5 Rock). Pour tous les autres types de données, tels que les données binaires, utilisez les API Filesystem et Sync Filesystem.

Les API Filesystem et Sync Filesystem de Chrome étendent l'API FileSystem HTML5. Avec l'API Filesystem de Chrome, les applications peuvent créer, lire, parcourir et écrire dans une section en bac à sable du système de fichiers local de l'utilisateur. Par exemple, une application de partage de photos peut utiliser l'API Filesystem pour lire et écrire les photos sélectionnées par un utilisateur.

Avec l'API Sync Filesystem de Chrome, les applications peuvent enregistrer et synchroniser des données sur le Google Drive d'un utilisateur, afin de les rendre disponibles dans différents clients. Par exemple, une application d'éditeur de texte sauvegardé dans le cloud peut synchroniser automatiquement les nouveaux fichiers texte avec le compte Google Drive d'un utilisateur. Lorsque l'utilisateur ouvre l'éditeur de texte dans un nouveau client, Google Drive transfère les nouveaux fichiers texte vers cette instance de l'éditeur.

Utiliser l'API Chrome Filesystem

Ajout d'une autorisation de système de fichiers...

Pour utiliser l'API File System de Chrome, vous devez ajouter l'autorisation "fileSystem" au fichier manifeste, afin d'obtenir l'autorisation de l'utilisateur pour stocker des données persistantes.

"permissions": [
  "...",
  "fileSystem"
]

Options utilisateur pour la sélection des fichiers

Les utilisateurs s'attendent à pouvoir sélectionner des fichiers comme d'habitude, au minimum un bouton "Sélectionner un fichier" et un sélecteur de fichier standard. Si votre application fait un usage intensif de la gestion des fichiers, vous devez également implémenter le glisser-déposer (voir ci-dessous, et consultez également Glisser-déposer HTML5 natif).

Obtenir le chemin d'accès d'un fileEntry

Pour obtenir le chemin d'accès complet du fichier sélectionné par l'utilisateur (fileEntry), appelez getDisplayPath():

function displayPath(fileEntry) {
  chrome.fileSystem.getDisplayPath(fileEntry, function(path) {
    console.log(path)
  });
}

Implémenter le glisser-déposer

Si vous devez implémenter la sélection par glisser-déposer, le contrôleur de fichiers par glisser-déposer (dnd.js) de l'exemple filesystem-access est un bon point de départ. Le contrôleur crée une entrée de fichier à partir d'un DataTransferItem par glisser-déposer. Dans cet exemple, fileEntry est défini sur le premier élément supprimé.

var dnd = new DnDFileController('body', function(data) {
  var fileEntry = data.items[0].webkitGetAsEntry();
  displayPath(fileEntry);
});

Lecture d'un fichier

Le code suivant ouvre le fichier (lecture seule) et le lit sous forme de texte à l'aide d'un objet FileReader. Si le fichier n'existe pas, une erreur est générée.

var chosenFileEntry = null;

chooseFileButton.addEventListener('click', function(e) {
  chrome.fileSystem.chooseEntry({type: 'openFile'}, function(readOnlyEntry) {

    readOnlyEntry.file(function(file) {
      var reader = new FileReader();

      reader.onerror = errorHandler;
      reader.onloadend = function(e) {
        console.log(e.target.result);
      };

      reader.readAsText(file);
    });
    });
});

Écrire un fichier

Les deux cas d'utilisation courants liés à l'écriture d'un fichier sont "Enregistrer" et "Enregistrer sous". Le code suivant crée un writableEntry à partir du chosenFileEntry en lecture seule et y écrit le fichier sélectionné.

 chrome.fileSystem.getWritableEntry(chosenFileEntry, function(writableFileEntry) {
    writableFileEntry.createWriter(function(writer) {
      writer.onerror = errorHandler;
      writer.onwriteend = callback;

    chosenFileEntry.file(function(file) {
      writer.write(file);
    });
  }, errorHandler);
});

Le code suivant crée un fichier avec la fonctionnalité "Enregistrer sous" et écrit le nouvel blob dans le fichier à l'aide de la méthode writer.write().

chrome.fileSystem.chooseEntry({type: 'saveFile'}, function(writableFileEntry) {
    writableFileEntry.createWriter(function(writer) {
      writer.onerror = errorHandler;
      writer.onwriteend = function(e) {
        console.log('write complete');
      };
      writer.write(new Blob(['1234567890'], {type: 'text/plain'}));
    }, errorHandler);
});

À l'aide de l'API Chrome Sync Filesystem

Grâce au stockage de fichiers synchronisable, les objets de données renvoyés peuvent être utilisés de la même manière que les systèmes de fichiers locaux hors connexion dans l'API FileSystem, mais avec la synchronisation ajoutée (et automatique) de ces données avec Google Drive.

Ajout de l'autorisation pour la synchronisation du système de fichiers...

Pour utiliser l'API Sync Filesystem de Chrome, vous devez ajouter l'autorisation "syncFileSystem" au fichier manifeste, afin d'obtenir l'autorisation de l'utilisateur pour stocker et synchroniser des données persistantes.

"permissions": [
  "...",
  "syncFileSystem"
]

Lancement du stockage de fichiers synchronisables

Pour lancer le stockage de fichiers synchronisables dans votre application, il vous suffit d'appeler syncFileSystem.requestFileSystem. Cette méthode renvoie un système de fichiers synchronisable sauvegardé par Google Drive, par exemple:

chrome.syncFileSystem.requestFileSystem(function (fs) {
   // FileSystem API should just work on the returned 'fs'.
   fs.root.getFile('test.txt', {create:true}, getEntryCallback, errorCallback);
});

À propos de l'état de la synchronisation des fichiers

Utilisez syncFileSystem.getFileStatus pour obtenir l'état de synchronisation d'un fichier actuel:

chrome.syncFileSystem.getFileStatus(entry, function(status) {...});

Les valeurs d'état de synchronisation des fichiers peuvent être 'synced', 'pending' ou 'conflicting'. "Synchronisé" signifie que le fichier est entièrement synchronisé ; il n'y a aucune modification locale en attente qui n'a pas été synchronisée avec Google Drive. Toutefois, dans Google Drive, il peut y avoir des modifications en attente qui n'ont pas encore été extraites.

"En attente" signifie que le fichier comporte des modifications en attente qui n'ont pas encore été synchronisées dans Google Drive. Si l'application s'exécute en ligne, les modifications locales sont (presque) immédiatement synchronisées avec Google Drive, et l'événement syncFileSystem.onFileStatusChanged est déclenché avec l'état 'synced' (voir ci-dessous pour plus d'informations).

Le script syncFileSystem.onFileStatusChanged est déclenché lorsque l'état d'un fichier passe à 'conflicting'. "En conflit" signifie que des modifications sont en conflit à la fois sur l'espace de stockage local et sur Google Drive. Cet état ne peut être appliqué à un fichier que si la règle de résolution des conflits est définie sur 'manual'. La règle par défaut est 'last_write_win', et les conflits sont automatiquement résolus par une règle simple de type "dernière écriture/victoire". La règle de résolution des conflits du système peut être modifiée à l'aide de la méthode syncFileSystem.setConflictResolutionPolicy.

Si la règle de résolution des conflits est définie sur 'manual' et qu'un fichier présente l'état 'conflicting', l'application peut toujours lire et écrire le fichier en tant que fichier hors connexion local. Toutefois, les modifications ne sont pas synchronisées, et le fichier est dissocié des modifications effectuées à distance sur les autres clients jusqu'à ce que le conflit soit résolu. Le moyen le plus simple de résoudre un conflit consiste à supprimer ou à renommer la version locale du fichier. Cela force la synchronisation de la version distante, l'état en conflit est résolu et l'événement onFileStatusChanged est déclenché avec l'état 'synced'.

Détecter les changements d'état synchronisé

L'événement syncFileSystem.onFileStatusChanged est déclenché lorsque l'état de synchronisation d'un fichier change. Par exemple, supposons qu'un fichier comporte des modifications en attente et qu'il soit à l'état "en attente". L'application était peut-être hors connexion, ce qui signifie que la modification est sur le point d'être synchronisée. Lorsque le service de synchronisation détecte la modification locale en attente et l'importe dans Google Drive, il déclenche l'événement onFileStatusChanged avec les valeurs suivantes : { fileEntry:a fileEntry for the file, status: 'synced', action: 'updated', direction: 'local_to_remote' }.

De même, quelles que soient les activités locales, le service de synchronisation peut détecter les modifications à distance apportées par un autre client et les télécharger depuis Google Drive vers l'espace de stockage local. Si la modification à distance concernait l'ajout d'un fichier, un événement avec les valeurs suivantes est déclenché : { fileEntry: a fileEntry for the file, status: 'synced', action: 'added', direction: 'remote_to_local' }.

Si le côté local et le côté distant présentent des modifications incompatibles pour le même fichier et que la règle de résolution des conflits est définie sur 'manual', l'état du fichier passe à l'état conflicting, il est dissocié du service de synchronisation et le fichier n'est pas synchronisé tant que le conflit n'est pas résolu. Dans ce cas, un événement avec les valeurs suivantes est déclenché : { fileEntry: a fileEntry for the file, status: 'conflicting', action: null, direction: null }.

Vous pouvez ajouter un écouteur pour cet événement, qui répond à tout changement d'état. Par exemple, l'application Lecteur de musique Chrome écoute toute nouvelle musique synchronisée à partir de Google Drive, mais qui n'a pas encore été importée dans l'espace de stockage local de l'utilisateur d'un client spécifique. Toute musique trouvée est synchronisée avec ce client:

chrome.syncFileSystem.onFileStatusChanged.addListener(function(fileInfo) {
  if (fileInfo.status === 'synced') {
    if (fileInfo.direction === 'remote_to_local') {
      if (fileInfo.action === 'added') {
        db.add(fileInfo.fileEntry);
      } else if (fileInfo.action === 'deleted') {
        db.remove(fileInfo.fileEntry);
      }
    }
  }
});

Vérifier l'utilisation de l'API

Pour vérifier la quantité de données utilisée par l'API, interrogez le répertoire local de bac à sable de l'application ou les octets d'utilisation renvoyés par syncFileSystem.getUsageAndQuota:

chrome.syncFileSystem.getUsageAndQuota(fileSystem, function (storageInfo) {
   updateUsageInfo(storageInfo.usageBytes);
   updateQuotaInfo(storageInfo.quotaBytes);
});

Vous pouvez également consulter l'espace de stockage du service de backend de synchronisation de l'utilisateur (dans Google Drive). Les fichiers synchronisés sont enregistrés dans un dossier Google Drive masqué, Chrome Syncable FileSystem. Le dossier n'apparaît pas dans votre liste "Mon Drive", mais vous pouvez y accéder en recherchant son nom dans le champ de recherche. (Notez que la rétrocompatibilité de la disposition du dossier distant entre les versions n'est pas garantie.)