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

相关推荐
y先森5 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy5 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189115 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿6 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡7 小时前
commitlint校验git提交信息
前端
虾球xz7 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇8 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒8 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员8 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐8 小时前
前端图像处理(一)
前端