На этом этапе вы узнаете:
- Как получить ссылку на файл во внешней файловой системе.
 - Как записать в файловую систему.
 
 Примерное время выполнения этого шага: 20 минут.
 Чтобы просмотреть то, что вы выполните на этом этапе, прыгните вниз этой страницы ↓ .
Экспортировать задачи
На этом этапе в приложение добавляется кнопка экспорта. При нажатии текущие элементы задач сохраняются в текстовый файл, выбранный пользователем. Если файл существует, он заменяется. В противном случае будет создан новый файл.
Обновить разрешения
Разрешения файловой системы можно запрашивать в виде строки для доступа только для чтения или объекта с дополнительными свойствами. Например:
// Read only
"permissions": ["fileSystem"]
// Read and write
"permissions": [{"fileSystem": ["write"]}]
// Read, write, autocomplate previous input, and select folder directories instead of files
"permissions": [{"fileSystem": ["write", "retainEntries", "directory"]}]
 Вам нужен доступ для чтения и записи. В файле Manifest.json запросите разрешение {fileSystem: [ "write" ] } :
"permissions": [
  "storage", 
  "alarms", 
  "notifications", 
  "webview",
  "<all_urls>", 
  { "fileSystem": ["write"] } 
],
Обновить HTML-представление
 В index.html добавьте кнопку «Экспорт на диск» и элемент div , в котором приложение отображает сообщение о состоянии:
<footer id="info">
  <button id="toggleAlarm">Activate alarm</button>
  <button id="exportToDisk">Export to disk</button>
  <div id="status"></div>
  ...
</footer>
Также в index.html загрузите скрипт Export.js :
...
<script src="js/alarms.js"></script>
<script src="js/export.js"></script>
Создать скрипт экспорта
Создайте новый файл JavaScript с именем Export.js, используя приведенный ниже код. Сохраните его в папке js .
(function() {
  var dbName = 'todos-vanillajs';
  var savedFileEntry, fileDisplayPath;
  function getTodosAsText(callback) {
  }
  function exportToFileEntry(fileEntry) {
  }
  function doExportToDisk() {
  }
  document.getElementById('exportToDisk').addEventListener('click', doExportToDisk);
})();
 На данный момент экспорт.js содержит только прослушиватель кликов на кнопке «Экспорт на диск» и заглушки для getTodosAsText() , exportToFileEntry и doExportToDisk() .
Получать задачи в виде текста
 Обновите getTodosAsText() , чтобы он считывал задачи из chrome.storage.local и генерировал их текстовое представление:
function getTodosAsText(callback) {
  chrome.storage.local.get(dbName, function(storedData) {
    var text = '';
    if ( storedData[dbName].todos ) {
      storedData[dbName].todos.forEach(function(todo) {
          text += '- ';
          if ( todo.completed ) {
            text += '[DONE] ';
          }
          text += todo.title;
          text += '\n';
        }, '');
    }
    callback(text);
  }.bind(this));
}
Выберите файл
 Обновите doExportToDisk() с помощью chrome.fileSystem.chooseEntry() чтобы позволить пользователю выбирать файл:
function doExportToDisk() {
  if (savedFileEntry) {
    exportToFileEntry(savedFileEntry);
  } else {
    chrome.fileSystem.chooseEntry( {
      type: 'saveFile',
      suggestedName: 'todos.txt',
      accepts: [ { description: 'Text files (*.txt)',
                   extensions: ['txt']} ],
      acceptsAllTypes: true
    }, exportToFileEntry);
  }
}
 Первый параметр chrome.fileSystem.chooseEntry() — это объект параметров. Второй параметр — метод обратного вызова.
 Если уже есть сохраненный FileEntry , используйте его при вызове exportToFileEntry() . Ссылки на файлы существуют в течение всего времени жизни объекта, представляющего FileEntry . В этом примере FileEntry привязывается к окну приложения, поэтому код JavaScript может записывать в выбранный файл без какого-либо взаимодействия с пользователем, пока окно приложения остается открытым.
Используйте FileEntry для записи элементов задач на диск
 Обновите exportToFileEntry() , чтобы сохранять задачи в виде текста через веб-API FileEntry :
function exportToFileEntry(fileEntry) {
  savedFileEntry = fileEntry;
  var status = document.getElementById('status');
  // Use this to get a file path appropriate for displaying
  chrome.fileSystem.getDisplayPath(fileEntry, function(path) {
    fileDisplayPath = path;
    status.innerText = 'Exporting to '+path;
  });
  getTodosAsText( function(contents) {
    fileEntry.createWriter(function(fileWriter) {
      var truncated = false;
      var blob = new Blob([contents]);
      fileWriter.onwriteend = function(e) {
        if (!truncated) {
          truncated = true;
          // You need to explicitly set the file size to truncate
          // any content that might have been there before
          this.truncate(blob.size);
          return;
        }
        status.innerText = 'Export to '+fileDisplayPath+' completed';
      };
      fileWriter.onerror = function(e) {
        status.innerText = 'Export failed: '+e.toString();
      };
      fileWriter.write(blob);
    });
  });
}
 chrome.fileSystem.getDisplayPath() получает отображаемый путь к файлу, который выводится в div статуса.
 Используйте fileEntry.createWriter() для создания объекта FileWriter . fileWriter.write() может затем записать Blob в файловую систему. Используйте fileWriter.onwriteend() и fileWriter.onerror() для обновления div статуса.
 Для получения дополнительной информации о FileEntry прочитайте Изучение API-интерфейсов файловой системы на HTML5Rocks или обратитесь к FileEntry docs на MDN.
Сохранение объектов FileEntry
 Дополнительно : объекты FileEntry не могут сохраняться бесконечно. Ваше приложение должно просить пользователя выбрать файл каждый раз при запуске приложения. Если ваше приложение было вынуждено перезапуститься из-за сбоя или обновления во время выполнения, restEntry() — это вариант восстановления FileEntry .
 Если хотите, поэкспериментируйте, сохранив идентификатор, возвращаемый функцией continueEntry() , и восстановив его при перезапуске приложения. (Подсказка: добавьте прослушиватель к событию onRestarted на фоновой странице.)
Запустите готовое приложение Todo.
Вы закончили Шаг 6! Перезагрузите приложение и добавьте несколько задач. Нажмите «Экспорт на диск» , чтобы экспортировать задачи в файл .txt.
Для получения дополнительной информации
Более подробную информацию о некоторых API, представленных на этом этапе, см.:
- Использование API файловой системы Chrome ↑
 - Объявить разрешения ↑
 - chrome.storage.local.get() ↑
 - chrome.fileSystem.chooseEntry() ↑
 - chrome.fileSystem.getDisplayPath() ↑
 - chrome.fileSystem.restoreEntry() ↑
 - chrome.fileSystem.retainEntry() ↑
 
Готовы перейти к следующему шагу? Перейдите к шагу 7. Опубликуйте свое приложение »