API хранилища

Почти каждый аспект разработки приложений включает в себя тот или иной элемент отправки или получения данных. Начиная с основ, вам следует использовать платформу MVC, которая поможет вам спроектировать и реализовать ваше приложение так, чтобы данные были полностью отделены от представления этих данных приложением (см. Архитектура MVC ).

Вам также необходимо подумать о том, как обрабатываются данные, когда ваше приложение находится в автономном режиме (см. «Сначала в автономном режиме »). В этом документе кратко представлены варианты хранения данных для отправки, получения и сохранения данных локально; В оставшейся части документа показано, как использовать API-интерфейсы файловой системы Chrome и синхронизации файловой системы (см. также API-интерфейсы fileSystem и syncFileSystem API ).

Варианты хранения

Упакованные приложения используют множество различных механизмов для отправки и получения данных. Для внешних данных (ресурсов, веб-страниц) необходимо знать Политику безопасности контента (CSP) . Подобно расширениям Chrome, вы можете использовать XMLHttpRequests из разных источников для связи с удаленными серверами. Вы также можете изолировать внешние страницы, чтобы остальная часть вашего приложения была в безопасности (см. Встраивание внешних веб-страниц ).

При локальном сохранении данных вы можете использовать Chrome Storage API для сохранения небольших объемов строковых данных и IndexedDB для сохранения структурированных данных. С помощью IndexedDB вы можете сохранять объекты JavaScript в хранилище объектов и использовать индексы хранилища для запроса данных (более подробную информацию см. в руководстве по простому списку задач HTML5 Rock). Для всех других типов данных, например двоичных данных, используйте API-интерфейсы файловой системы и синхронизации файловой системы.

API файловой системы и синхронизации файловой системы Chrome расширяют API файловой системы HTML5 . С помощью API файловой системы Chrome приложения могут создавать, читать, перемещаться и записывать в изолированный раздел локальной файловой системы пользователя. Например, приложение для обмена фотографиями может использовать API файловой системы для чтения и записи любых фотографий, которые выбирает пользователь.

С помощью API синхронизации файловой системы Chrome приложения могут сохранять и синхронизировать данные на Google Диске пользователя, чтобы одни и те же данные были доступны различным клиентам. Например, приложение для текстового редактора с поддержкой облака может автоматически синхронизировать новые текстовые файлы с учетной записью пользователя на Google Диске. Когда пользователь открывает текстовый редактор в новом клиенте, Google Диск отправляет новые текстовые файлы в этот экземпляр текстового редактора.

Использование API файловой системы Chrome

Добавление разрешения файловой системы

Чтобы использовать API файловой системы Chrome, вам необходимо добавить в манифест разрешение «fileSystem», чтобы вы могли получить от пользователя разрешение на хранение постоянных данных.

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

Пользовательские параметры выбора файлов

Пользователи ожидают, что будут выбирать файлы так же, как они это делают всегда. Как минимум, они ожидают кнопку «Выбрать файл» и стандартный инструмент выбора файла. Если ваше приложение активно использует обработку файлов, вам также следует реализовать перетаскивание (см. ниже, а также ознакомьтесь со статьей Native HTML5 Drag and Drop ).

Получение пути к файлуEntry

Чтобы получить полный путь к файлу, выбранному пользователем, fileEntry , вызовите getDisplayPath() :

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

Реализация перетаскивания

Если вам нужно реализовать выбор методом перетаскивания, хорошей отправной точкой будет файловый контроллер перетаскивания ( dnd.js ) в примере доступа к файловой системе . Контроллер создает запись файла из DataTransferItem посредством перетаскивания. В этом примере fileEntry задан первый удаленный элемент.

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

Чтение файла

Следующий код открывает файл (только для чтения) и считывает его как текст с помощью объекта FileReader . Если файл не существует, выдается ошибка.

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);
    });
    });
});

Написание файла

Двумя распространенными вариантами записи файла являются «Сохранить» и «Сохранить как». Следующий код создает writableEntry из chosenFileEntry доступного только для чтения, и записывает в него выбранный файл.

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

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

Следующий код создает новый файл с функцией «Сохранить как» и записывает в него новый большой двоичный объект с помощью метода 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);
});

Использование API файловой системы синхронизации Chrome

Используя синхронизируемое хранилище файлов, с возвращаемыми объектами данных можно работать так же, как с локальными автономными файловыми системами в API файловой системы , но с добавленной (и автоматической) синхронизацией этих данных с Google Диском.

Добавление разрешения на синхронизацию файловой системы

Чтобы использовать API синхронизации файловой системы Chrome, вам необходимо добавить в манифест разрешение «syncFileSystem», чтобы вы могли получить от пользователя разрешение на хранение и синхронизацию постоянных данных.

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

Запуск синхронизируемого хранилища файлов

Чтобы инициировать синхронизируемое хранилище файлов в вашем приложении, просто вызовите syncFileSystem.requestFileSystem . Этот метод возвращает синхронизируемую файловую систему, поддерживаемую Google Диском, например:

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

О статусе синхронизации файлов

Используйте syncFileSystem.getFileStatus , чтобы получить статус синхронизации текущего файла:

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

Значения состояния синхронизации файлов могут быть одним из следующих: 'synced' , 'pending' или 'conflicting' . «Синхронизировано» означает, что файл полностью синхронизирован; нет ожидающих рассмотрения локальных изменений, которые не были синхронизированы с Google Диском. Однако на стороне Google Диска могут быть ожидающие изменения, которые еще не были загружены.

«Ожидание» означает, что в файле есть ожидающие изменения, которые еще не синхронизированы с Google Диском. Если приложение работает онлайн, локальные изменения (почти) немедленно синхронизируются с Google Диском, а событие syncFileSystem.onFileStatusChanged запускается со статусом 'synced' (более подробную информацию см. ниже).

syncFileSystem.onFileStatusChanged запускается, когда статус файла меняется на 'conflicting' . «Конфликт» означает, что в локальном хранилище и на Google Диске имеются конфликтующие изменения. Файл может находиться в этом состоянии только в том случае, если для политики разрешения конфликтов установлено значение 'manual' . Политика по умолчанию — 'last_write_win' и конфликты автоматически разрешаются с помощью простой политики «последняя запись выиграла». Системную политику разрешения конфликтов можно изменить с помощью syncFileSystem.setConflictResolutionPolicy .

Если для политики разрешения конфликтов установлено значение 'manual' , а файл приводит к 'conflicting' состоянию, приложение все равно может читать и записывать файл как локальный автономный файл, но изменения не синхронизируются, и файл сохраняется. отключен от удаленных изменений, внесенных на других клиентах, до разрешения конфликта. Самый простой способ разрешить конфликт — удалить или переименовать локальную версию файла. Это принудительно синхронизирует удаленную версию, конфликтное состояние разрешается, и событие onFileStatusChanged запускается со статусом 'synced' .

Прослушивание изменений в статусе синхронизации

Событие syncFileSystem.onFileStatusChanged вызывается при изменении состояния синхронизации файла. Например, предположим, что файл имеет ожидающие изменения и находится в состоянии «ожидания». Возможно, приложение находилось в автономном состоянии, поэтому изменения будут синхронизированы. Когда служба синхронизации обнаруживает ожидающее локальное изменение и загружает его на Google Диск, служба запускает событие onFileStatusChanged со следующими значениями: { fileEntry:a fileEntry for the file, status: 'synced', action: 'updated', direction: 'local_to_remote' } .

Аналогичным образом, независимо от локальных действий, служба синхронизации может обнаруживать удаленные изменения, внесенные другим клиентом, и загружает изменения с Google Диска в локальное хранилище. Если удаленное изменение было связано с добавлением нового файла, создается событие со следующими значениями: { fileEntry: a fileEntry for the file, status: 'synced', action: 'added', direction: 'remote_to_local' } .

Если как на локальной, так и на удаленной стороне имеются конфликтующие изменения для одного и того же файла и если для политики разрешения конфликтов установлено значение 'manual' , состояние файла изменяется на conflicting состояние, он отсоединяется от службы синхронизации и не будет синхронизирован до тех пор, пока конфликт разрешен. В этом случае запускается событие со следующими значениями: { fileEntry: a fileEntry for the file, status: 'conflicting', action: null, direction: null } .

Вы можете добавить прослушиватель этого события, который будет реагировать на любые изменения статуса. Например, приложение Chrome Music Player прослушивает любую новую музыку, синхронизированную с Google Диска, но еще не импортированную в локальное хранилище пользователя на конкретном клиенте. Любая найденная музыка синхронизируется с этим клиентом:

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);
      }
    }
  }
});

Проверка использования API

Чтобы проверить объем данных, используемых API, запросите локальный изолированный каталог приложения или байты использования, возвращаемые syncFileSystem.getUsageAndQuota :

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

Вы также можете просмотреть хранилище серверной службы синхронизации пользователя (на Google Диске). Синхронизированные файлы сохраняются в скрытой папке Google Диска Chrome Syncable FileSystem . Папка не будет отображаться в вашем списке «Мой диск», но к ней можно будет получить доступ, выполнив поиск по имени папки в поле поиска. (Обратите внимание, что макет удаленной папки не гарантирует обратную совместимость между выпусками.)