在這個步驟中,您將瞭解:
- 如何取得外部檔案系統中的檔案參照。
- 如何寫入檔案系統。
預估完成這項步驟的時間: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 中,新增「Export to disk」按鈕和 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()
、exportToFileEntry
和 doExportToDisk()
的 Stub。
以文字格式取得待辦事項
更新 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
繫結至應用程式視窗,因此只要應用程式視窗保持開啟狀態,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 上的「Exploring the FileSystem APIs」(探索 FileSystem API),或參閱 MDN 上的 FileEntry docs
。
將 FileEntry 物件儲存為持久性
進階:FileEntry
物件無法無限期保留。應用程式每次啟動時,都必須要求使用者選擇檔案。如果應用程式因執行階段當機或更新而被迫重新啟動,您可以使用 restoreEntry() 選項還原 FileEntry
。
如有需要,您可以儲存 retainEntry() 傳回的 ID,並在應用程式重新啟動時還原。(提示:在背景頁面中為 onRestarted
事件新增監聽器)。
啟動完成的 Todo 應用程式
您已完成步驟 6!重新載入應用程式並新增待辦事項。按一下「匯出至磁碟」,將待辦事項匯出為 .txt 檔案。
瞭解詳情
如要進一步瞭解此步驟中介紹的部分 API,請參閱:
- 使用 Chrome 檔案系統 API ↑
- 宣告權限 ↑
- chrome.storage.local.get() ↑
- chrome.fileSystem.chooseEntry() ↑
- chrome.fileSystem.getDisplayPath() ↑
- chrome.fileSystem.restoreEntry() ↑
- chrome.fileSystem.retainEntry() ↑
準備繼續進行下一個步驟了嗎?請參閱「步驟 7 - 發布應用程式 »