用 file system access api 批量储存文件
2021-03-03
最近有个热门项目,在 github.com 的域名后面加 1s,就可以打开一个编辑器,查看项目代码,非常好用,寿命+1s.
其中,可以右键某个文件夹,把这个文件夹目录下的文件下载到本地,会弹两个授权提醒,允许网站查看文件 和 将所作更改保存至xxx , 但是没有疯狂的文件保存对话框,对于保存多个文件非常有用。找了一下找到还是 draft 状态的 File System Access API。 吐槽一下一开始在 MDN 搜索,找到了 File and Directory Entries API, 根本不是一个东西。
对 File System Access API 进行一个瞧
大致看了下,这个api可以读取文件和文件夹,并且枚举文件夹内容,修改文件并保存,所有操作都是 promise 形式, 因此写下来一堆 await,另外 api 有 Secure Contexts 限制,只能在https环境下使用。另外这个api只支持 chrome 86+ ,说不定以后还会改掉。
wicg 草案:https://wicg.github.io/file-system-access
MDN 的文档: https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API
web.dev 的介绍: https://web.dev/file-system-access
api使用大概都是这样:
- 选取文件/文件夹
- 打开文件夹
window.showDirectoryPicker() - 打开文件
window.showOpenFilePicker()
可以传入option 配置是否多选和可选的文件MIME TYPE,根据参数可能返回[FileSystemFileHandle]数组- 保存文件对话框
window.showSaveFilePicker()参数基本同上,限定保存格式,返回FileSystemFileHandle
- 打开文件夹
- 通过 Picker 得到对应的 Handler 接口 ,用 Handler 对象进行相应的操作
FileSystemHandle下面两个的"父接口" ,有下面两个接口的一些通用方法FileSystemFileHandle操作单独一个文件的接口
使用getFile()读取文件,使用createWritable()获得文件的FileSystemWritableFileStream接口,操作文件。FileSystemDirectoryHandle文件夹接口,方法比较多。FileSystemDirectoryHandle.getFileHandle()读取文件/新建文件,返回FileSystemWritableFileStreamFileSystemDirectoryHandle.getDirectoryHandle()读取子目录/新建目录,进行一个套娃。FileSystemDirectoryHandle.keys()遍历目录。
FileSystemWritableFileStream写入文件的接口。write写入二进制文件,seek写入光标导航,truncate把文件调整为指定大小(字节),close关闭文件,并存到硬盘上,不调用这个,文件的改动不会存到硬盘上。
接口大概是这样,很多细节还不是太清楚,这里要批量存储文件的话主要靠循环调用 FileSystemDirectoryHandle.getFileHandle() 进行文件的储存,同一个页面对同一个文件夹只需要授权一次,所以体验比一大堆保存文件弹框要好点。
保存单个文件的示例
document.querySelector('#btn').addEventListener('click',async ()=>{
const blob = await (await fetch('https://files.catbox.moe/agyqq6.png')).blob()
const dirHandler = await window.showDirectoryPicker()
const fileHandler = await dirHandler.getFileHandle('test.png',{create:true})
const writable = await fileHandler.createWritable()
await writable.write(blob);
await writable.close()
})
用户脚本
实际用起来比模拟a标签点击的批量下载方便一些,以后用户脚本能干更多坏事了。
批量下载tumblr图片:https://github.com/shadowdreamer/jioben/blob/master/others/tumblr-image-download.user.js
简单测试,效果ok,chrome版本88,因为差不多是自用脚本,所以没有做低版本浏览器兼容。