На этом этапе вы узнаете:
- Как получить ссылку на файл во внешней файловой системе.
- Как записать в файловую систему.
Примерное время выполнения этого шага: 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. Публикация приложения »