第 6 步:将待办事项导出到文件系统

在此步骤中,您将了解以下内容:

  • 如何获取对外部文件系统中文件的引用。
  • 如何写入文件系统。

完成此步骤预计需要 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>

创建导出脚本

使用以下代码创建一个名为 export.js 的新 JavaScript 文件。将其保存在 js 文件夹中。

(function() {

 
var dbName = 'todos-vanillajs';

 
var savedFileEntry, fileDisplayPath;

 
function getTodosAsText(callback) {
 
}

 
function exportToFileEntry(fileEntry) {
 
}

 
function doExportToDisk() {
 
}

  document
.getElementById('exportToDisk').addEventListener('click', doExportToDisk);

})();

目前,export.js 仅包含 Export to disk 按钮的点击监听器,以及 getTodosAsText()exportToFileEntrydoExportToDisk() 的桩。

以文本形式获取待办事项

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

选择一个文件

使用 chrome.fileSystem.chooseEntry() 更新 doExportToDisk(),以允许用户选择文件:

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 的对象的生命周期内存在。此示例将 FileEntry 绑定到应用窗口,因此只要应用窗口保持打开状态,JavaScript 代码就可以在不进行任何用户交互的情况下写入所选文件。

使用 FileEntry 将待办事项写入磁盘

更新 exportToFileEntry(),以便通过 FileEntry Web API 将待办事项保存为文本:

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,请参阅 HTML5Rocks 上的 探索 FileSystem API,或参阅 MDN 上的 FileEntry docs

保留 FileEntry 对象

高级FileEntry 对象无法无限期保留。您的应用需要在每次启动时都要求用户选择文件。如果您的应用因运行时崩溃或更新而被迫重启,则可以使用 restoreEntry() 恢复 FileEntry

如果您愿意,可以通过保存 retainEntry() 返回的 ID 并在应用重启时恢复该 ID 来进行实验。(提示:在后台页面中向 onRestarted 事件添加监听器。)

启动完成开发的 Todo 应用

您已完成第 6 步!重新加载您的应用,然后添加一些待办事项。点击导出到磁盘,将您的待办事项导出为 .txt 文件。

包含导出的待办事项的“Todo”应用

了解详情

如需详细了解本步骤中介绍的部分 API,请参阅:

准备好继续执行下一步了吗?前往第 7 步 - 发布应用 »