经常看见有人提问怎么去下载文件、保存文件之类的问题的,一直是说用File System Access API 但是怎么用,从没说过,今天来研究一下,顺便写一些示例
使用之前,先注意一下浏览器兼容性Firefox是完全不支持,另外依旧有一些局限性,需要用户手动触发操作
获取权限
window.showOpenFilePicker/showDirectoryPicker
这两个API用于打开一个窗口,授权文件/目录,例如下面这样
async function getFile() {
// open directory picker
const dirHandle = await window.showDirectoryPicker();
console.log(dirHandle);
}
getFile();
调用后会打开一个窗口,选择允许查看的文件目录~~~~
确认授权
完成后会返回一个下面这样的结构体
但是刷新页面后,会报下面这个错误,必须要有用户操作触发才行(但是不知道为什么第一次是可以的。。。)
Failed to execute 'showDirectoryPicker' on 'Window': Must be handling a user gesture to show a file picker.
像这样,在这里我指定来一个参数{mode:"readwrite"},这样就可以获取目录的读写权限,对目录为所欲为
const button = document.createElement('button');
button.innerText = "点我授权目录";
document.body.firstChild.after(button);
button.addEventListener('click', async function () {
async function getFile() {
// open directory picker
const dirHandle = await window.showDirectoryPicker({mode:"readwrite"});
console.log(dirHandle);
}
getFile();
});
另外我发现返回的dirHandle的对象是可以存到indexedDB(可以存储js 对象)中去的,但是不清楚能不能继续给下次调用,有兴趣的朋友可以试试。
读写文件
既然获取到了权限,就来试试能不能操作本地文件,获取到的对象是:FileSystemDirectoryHandle,更多内容可看MDN
const button2 = document.createElement('button');
button2.innerText = "点我读取目录&写点东西";
document.body.firstChild.after(button2);
button2.addEventListener('click', async function () {
// 读取目录
for await (const item of dirHandle.values()) {
console.log(item)
}
// 写文件
const fileHandle = await dirHandle.getFileHandle("hello-world.txt", { create: true });
const writable = await fileHandle.createWritable();
await writable.write("Hello World!");
await writable.close();
});
END
简单过了一下FileSystemAPI,感觉还是很强大的,应该能衍生不少玩法