前言
很久以来,浏览器都没有修改本地文件的权限,直到chrome 86 起支持File System Access API。
这个 API 允许与用户本地设备或用户可访问的网络文件系统上的文件进行交互,核心功能主要是读取文件、写入或创建文件以及访问文件夹。
历史
事实上,在这个稳定的API之前,历史上有过很多浏览器操作本地文件的尝试。
最早的是 File API,代表功能是 FileReader。
后来,Chrome提供了 File System API。这个 API 能在浏览器里创建一个独立的文件环境,但是无法操作系统本地文件,所以最终这套方案死得悄无声息。
接下来是 Chrome Extension、Chrome App、Chrome OS 里的 File System API。目前,这几个API已经弃用,因为有了更佳的解决方案,也就是今天我要介绍的,File System Access API。
使用
File System Access API 提供了比较稳妥的本地文件交互模式,即保证了实用价值,又保障了用户的数据安全,除非用户明确允许,否则不允许进行读写。
读写文件都是异步操作,它们都会用到async,或使用迭代器时会用到yield。
我们直接来看代码:
JS与用户的交互有三个API,它们都会返回一个promise,我们直接在f12中输入这些代码就可以看到效果
window.showOpenFilePicker() // 打开本地文件
window.showSaveFilePicker() // 创建一个新文件
window.showDirectoryPicker() // 打开本地文件夹
window.showOpenFilePicker()和window.showSaveFilePicker()都是与文件相关的,调用其中任何一个方法,我们都能在promise.then中得到一个数组:
我们来观察一下,这个数组只有一项,显然就是你选择的这个文件,如果你选择多个文件,数组就会有多个对象
这个对象的原型是FileSystemFileHandle,有kind和name两个属性(其实是从父级继承的)
原型上有两个方法,分别是getFile和createWritable,显然,一个是读,一个是写。
下面是一个demo,我们运行getFile()方法,将fileHandle对象保存到全局,然后我们可以通过getText()读取内容,writeFile()写入内容。
可以注意到写入文件的时候我们通过createWritable()方法创建了一个FileSystemWritableFileStream对象,当createWritable()被调用时,浏览器首先检查用户是否授予了文件的写权限。如果未授予写入权限,浏览器将提示用户授予权限。如果未授予权限,createWritable()将抛出一个DOMException,无法写入。
let fileHandle
async function getFile () {
[ fileHandle ] = await window.showOpenFilePicker()
}
async function getText () {
const file = await fileHandle.getFile()
const text = await file.text()
console.log(text)
}
async function writeFile () {
const writable = await fileHandle.createWritable()
await writable.write('测试一下')
await writable.close()
}
window.showDirectoryPicker()与上一个相似,具体就不细讲了,无非就是提供了异步迭代、删除文件等方法。
结语
这个API的功能是很强大的,算是对一些问题提供了一个新的解决方案。
参考文档
https://www.31du.cn/software/chrome-86.html chrome86更新内容
https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API API文档
https://googlechromelabs.github.io/text-editor/ 官方demo
https://github.com/GoogleChromeLabs/text-editor/ demo的github地址 我从中找到了文件临时缓存的解决方案:indexDB
https://web.dev/file-system-access/#what-is-it 使用文档
https://wicg.github.io/file-system-access/ API文档(更细)
https://blog.meathill.com/js/use-file-system-access-api-to-handle-local-files.html File API 历史参考