令人兴奋的浏览器文件系统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的优势。

相关推荐
Fan_web4 分钟前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常6 分钟前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式
莹雨潇潇1 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
Jiaberrr1 小时前
Element UI教程:如何将Radio单选框的圆框改为方框
前端·javascript·vue.js·ui·elementui
Tiffany_Ho2 小时前
【TypeScript】知识点梳理(三)
前端·typescript
安冬的码畜日常3 小时前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
小白学习日记3 小时前
【复习】HTML常用标签<table>
前端·html
丁总学Java4 小时前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js
yanlele4 小时前
前瞻 - 盘点 ES2025 已经定稿的语法规范
前端·javascript·代码规范