透過這個 File System Access API 就能透過程式操作本機上的檔案,舉例來說像是開啟或儲存檔案等,部分瀏覽器會需要給予相關的權限才能進行操作,除了開啟檔案 API 本身也提供了開啟目錄並列舉檔案列表的功能。
對 Progressive Web App 也會在某些情境需要可以存取和操作本機端的檔案,Google 的 Lab 提供了底下這個編輯器可以簡單試玩:
https://googlechromelabs.github.io/text-editor/
browser-fs-access library:
https://github.com/GoogleChromeLabs/browser-fs-access
小編在幾年前剛學習 SPA 時也寫了個單頁筆記的應用,能夠快速的寫一些筆記,也附上原始碼和 Demo 連結。
原始碼: https://github.com/LinYenCheng/vue-note
Demo 連結: https://linyencheng.github.io/vue-note/
前幾年小編其實沒有使用過 File System Access API,所以顯然在操作上其實有兩種方式,那第一種是透過原生的 input
然後指定 type
為 file
就可以達到讀取的效果,第二種是透過 File System Access API 的 showOpenFilePicker()
。
<input type="file" id="fileInput">
並且簡單撰寫相關事件就能夠使用,程式碼如下:
var fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function(e) {
var file = fileInput.files[0];
var textType = /text.*/;
if (file.type.match(textType)) {
var reader = new FileReader();
reader.onload = function(e) {
maindata.gridData = [];
var objText = JSON.parse(reader.result.toString());
objText.gridData.forEach(function(element, index) {
maindata.gridData.push(element);
});
console.log(objText);
};
reader.readAsText(file);
} else {
fileDisplayArea.innerText = "File not supported!";
}
});
showOpenFilePicker()
,最後取得的 File object 包含會一個 blob 可以透過以下的方法去取得相關的值:let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker({
// 可以提供預設
startIn: 'pictures'
});
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});
showOpenFilePicker
中的 startIn
提供的預設值是常見的幾個資料夾,能夠提供指定
操作上一樣會有兩種方式,第一種是產生出一個下載連結,將 Blob 檔案透過下載的方式寫入,第二種是透過 File System Access API 的 showSaveFilePicker()
。
function saveFile(text) {
var url = null;
var data = new Blob([text], {
type: 'text/plain;'
});
// If we are replacing a previously generated file we need to
// manually revoke the object URL to avoid memory leaks.
if (url !== null) {
window.URL.revokeObjectURL(url);
}
url = window.URL.createObjectURL(data);
var link = document.getElementById('exportText');
link.href = url;
var filename = window.prompt("輸入檔名") || 'export';
link.download = filename + '.txt';
link.click();
}
showSaveFilePicker()
開啟選擇寫入資料夾的視窗。
const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});
async function writeFile(fileHandle, contents) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();
}
這個之前小編就沒有試過其他方式,那透過 File System Access API 的 removeEntry()
是可以做到刪除檔案和刪除資料夾所有內容的效果。
// 刪除檔案
await directoryHandle.removeEntry('Abandoned Projects.txt');
// 刪除資料夾所有內容
await directoryHandle.removeEntry('Old Stuff', { recursive: true });
File System Access API 的 showDirectoryPicker()
提供了我們操作目錄並列舉內容的功能。
const dirHandle = await window.showDirectoryPicker();
for await (const entry of dirHandle.values()) {
console.log(entry.kind, entry.name);
}
部分瀏覽器環境還是會有權限的問題,所以偵測權限相關就變成也是要寫在程式碼裡,邏輯如下:
async function verifyPermission(fileHandle, readWrite) {
const options = {};
if (readWrite) {
options.mode = 'readwrite';
}
// 看是否已同意
if ((await fileHandle.queryPermission(options)) === 'granted') {
return true;
}
// 看這次有沒有要成功
if ((await fileHandle.requestPermission(options)) === 'granted') {
return true;
}
// 被拒絕
return false;
}