令人兴奋的浏览器文件系统API

在传统浏览器中,浏览器应用程序只能访问网页资源,而网页资源是存储在服务器上的。这意味着像 Photoshop、VSCode 等应用程序无法在浏览器中运行,因为它们需要访问本地文件。浏览器文件系统 API 的出现,打破了这一局限,为像 Photoshop、VSCode 等应用程序在浏览器中运行提供了基础。下面我们来看看浏览器怎么操作系统文件。

showOpenFilePicker 选取文件

showOpenFilePicker() 方法用于显示一个文件选择器,允许用户选择一个或多个文件。返回值是一个 File[] 数组,其中包含用户选择的文件句柄。当未指定任何选项时,只允许用户选择单个文件。

html 复制代码
<button @click="openFilePicker">打开文件</button>
js 复制代码
export default {
  methods: {
    async openFilePicker() {
      const [fileHandle] = await window.showOpenFilePicker()
      // 文件操作
    },
  },
}

点击按钮后,效果如下图所示:

读取文件

有了文件句柄,我们可以获取文件的属性,或者访问文件本身。通过getFile()获取 File 对象,然后通过 File 对象的方法(如slice()stream()text()arrayBuffer())来读取文件内容。

js 复制代码
const file = await fileHandle.getFile()
const contents = await file.text()

保存文件

showSaveFilePicker() 方法用于保存文件,可以创建一个新的文件,如创建一个空的 .txt 文件。

js 复制代码
async getNewFileHandle() {
  const options = {
    types: [
      {
        description: 'Text Files',
        accept: {
          'text/plain': ['.txt'],
        },
      },
    ],
  };
  const handle = await window.showSaveFilePicker(options);
  return handle;
}

以下是一些 options 的设置:

  1. suggestedName :设置默认文件名,例如 suggestedName: 'Untitled Text.txt'
  2. startIn :设置默认启动目录,例如 startIn: 'desktop' 会打开桌面目录,还有其他可选的值包括 documentsdownloadsmusicpicturesvideos 等。当然也可以是已知的文件或目录句柄。
  3. id :通过设置 id,可以让文件系统记住你打开过的目录位置。例如,当新建文件时设置id: "img",第一次选取了目录 /path/to/img,下次使用 id: "img" 时就能够直接定位到这个目录。

写入文件

要将数据写入磁盘,可以使用 FileSystemWritableFileStream 对象,它是 WritableStream 的一个子类。通过调用文件句柄对象创建流。在调用时,浏览器会首先检查用户是否已经授予对文件的写入权限。如果用户尚未授予写入权限,浏览器会提示用户进行授权。如果用户没有授权,则无法写入文件。

js 复制代码
async writeFile(fileHandle, contents) {
  // 创建一个 FileSystemWritableFileStream 用于写入
  const writable = await fileHandle.createWritable();
  // 写入我们的文件
  await writable.write(contents);
  // 关闭文件并将内容写入到磁盘
  await writable.close();
}

利用文件写入操作,还可以应用于流式下载文件。传统的文件下载方式使用 <a> 标签,需要加载完整文件,等待时间长,而且会消耗大量内存。使用流式下载就可以解决这个问题,而且可以摆脱依赖于像 StreamSaver.js 这样的库。

js 复制代码
async function writeURLToFile(fileHandle, url) {
  const writable = await fileHandle.createWritable()
  const response = await fetch(url)
  await response.body.pipeTo(writable)
}

showDirectoryPicker 选取目录

使用 showDirectoryPicker() 方法可以让用户选择一个目录,然后返回一个 FileSystemDirectoryHandle 对象。该目录句柄允许您枚举和访问该目录中的文件。默认情况下,您具有对目录中文件的读取权限,但如果需要写入权限,可以通过 { mode: 'readwrite' } 参数进行传递。

js 复制代码
async openDirectoryPicker() {
  const dirHandle = await window.showDirectoryPicker();
  for await (const entry of dirHandle.values()) {
    console.log(entry.kind, entry.name);
  }
}

创建文件夹或文件

对于已经存在的目录句柄,可以使用 getDirectoryHandle() 方法创建文件夹,或使用 getFileHandle() 方法创建文件。

js 复制代码
// 新建文件夹
const newDirectoryHandle = await existingDirectoryHandle.getDirectoryHandle('New Documents', {
  create: true,
})
// 新建文件
const newFileHandle = await newDirectoryHandle.getFileHandle('New Notes.txt', { create: true })

值得注意的是,使用 getFileHandle() 创建文件时不会弹出文件选择框,而是直接将文件添加到您的系统文件中,这一点与前面提到的保存新文件是不一样的。

删除文件夹或文件

可以使用 removeEntry() 方法来删除文件和文件夹。对于文件夹,可以选择递归删除,包括所有子文件夹和其中包含的文件。

js 复制代码
// 删除文件
await newDirectoryHandle.removeEntry('New Notes.txt')

// 删除文件夹
await existingDirectoryHandle.removeEntry('New Documents', { recursive: true })

还可以直接使用文件或文件夹句柄的 remove() 方法进行删除。

js 复制代码
await newDirectoryHandle.remove({ recursive: true })

await newFileHandle.remove()

删除目录时,如果目录不为空,需要添加 { recursive: true } 参数来递归删除子目录和文件,否则无法删除目录。

移动或重命名

可以使用 move() 方法来移动或重命名文件。实际上,重命名操作本质上也是一个移动操作。

js 复制代码
// 文件重命名为 Notes.txt
await newFileHandle.move('Notes.txt')
// 移动到新的文件夹
await newFileHandle.move(existingDirectoryHandle)
// 移动到新的文件夹并重命名为Notes.txt
await newFileHandle.move(existingDirectoryHandle, 'Notes.txt')

浏览器文件系统API的强大之处令人惊叹,它为未来浏览器应用程序的发展创造了广阔的前景。随着技术的不断进步,我们可以预见到更多应用程序将转移到浏览器平台,并利用文件操作API的优势。

相关推荐
anyup_前端梦工厂2 小时前
了解几个 HTML 标签属性,实现优化页面加载性能
前端·html
前端御书房2 小时前
前端PDF转图片技术调研实战指南:从踩坑到高可用方案的深度解析
前端·javascript
2301_789169542 小时前
angular中使用animation.css实现翻转展示卡片正反两面效果
前端·css·angular.js
风口上的猪20153 小时前
thingboard告警信息格式美化
java·服务器·前端
程序员黄同学3 小时前
请谈谈 Vue 中的响应式原理,如何实现?
前端·javascript·vue.js
爱编程的小庄4 小时前
web网络安全:SQL 注入攻击
前端·sql·web安全
宁波阿成4 小时前
vue3里组件的v-model:value与v-model的区别
前端·javascript·vue.js
柯腾啊5 小时前
VSCode 中使用 Snippets 设置常用代码块
开发语言·前端·javascript·ide·vscode·编辑器·代码片段
weixin_535854225 小时前
oppo,汤臣倍健,康冠科技,高途教育25届春招内推
c语言·前端·嵌入式硬件·硬件工程·求职招聘
扣丁梦想家5 小时前
设计模式教程:装饰器模式(Decorator Pattern)
java·前端·装饰器模式