File System API前端文件系统API

文件系统API

在没有文件系统API之前,JS是不能对磁盘中的文件进行修改 写入磁盘的,有了File System API之后,就能对电脑设备磁盘中的文件进行修改,删除,创建(为了安全只能对非系统文件进行操作,且必须得到用户授权)

文件系统 API (File System API)------以及通过文件系统访问 API(File System Access API)提供的方法来访问设备中的文件或者文件夹,并可以对文件,文件夹进行创建,修改,等操作

注意:仅在部分浏览器支持


使用说明

大多数与文件和目录的交互都通过句柄来完成。通过调用全局方法来让用户选择文件,或者选择文件夹。之后就能得到这些 文件句柄对象,目录句柄对象,最后通过这些句柄对象来操作文件或目录

全局方法

打开文件对话框

方法window.showOpenFilePicker()用于打开一个文件选择器对话框,允许用户选择一个或者多个文件并返回这些文件的句柄

示例

js 复制代码
const pickerOpts = {
  types: [
    {
      description: "Images",
      accept: {
        "image/*": [".png", ".gif", ".jpeg", ".jpg"],
      },
    },
  ],
  excludeAcceptAllOption: true, // 是否开启过滤器
  multiple: false,  // 是否可多选文件
  startIn: 'desktop'  // ("desktop"、"documents"、"downloads"、"music"、"pictures" 或 "videos")以指定打开选择器的起始目录
};
async function getFile() {
  // 打开文件选择器,得到文件句柄列表数组
  const fileHandles = await window.showOpenFilePicker(pickerOpts);
  // 操作 fileHandle 的后续代码,具体看文件句柄章节
}

打开文件保存对话框

方法 window.showSaveFilePicker() 方法用于打开一个文件选择器,以允许用户保存一个文件。可以选择一个已有文件覆盖保存,也可以输入名字新建一个文件。

示例

js 复制代码
async function getNewFileHandle() {
  const opts = {
    types: [
      {
        description: "Text file",  // 默认文件名
        accept: { "text/plain": [".txt"] },
      },
    ],
    excludeAcceptAllOption: true, // 是否开启过滤器
    multiple: false,  // 是否可多选文件
    startIn: 'desktop'  // ("desktop"、"documents"、"downloads"、"music"、"pictures" 或 "videos")以指定打开选择器的起始目录
  };
  // 保存后得到文件句柄,之后可通过该文件句柄来写入数据,具体看文件句柄章节
  const fileHandle await window.showSaveFilePicker(opts);
  return fileHandle
}

打开目录对话框

方法window.showDirectoryPicker()方法用于打开一个目录选择器,以允许用户选择一个目录。之后得到该目录的句柄,通过这个句柄,可对该文件夹内的文件进行,删除,修改,创建新文件

示例

js 复制代码
const option = {
    mode: "readwrite", // 默认为 "read",用于只读访问,或 "readwrite" 用于读写访问
    startIn: 'desktop'  // 默认起始目录
}

async function getDir() {
  // 得到目录句柄
  const dirHandle = await window.showDirectoryPicker(option);
  // 通过句柄,可对文件夹内文件进行 增删改查
}

拖拽接收文件或目录

通过drop事件对象,调用getAsFileSystemHandle方法,得到一个 FileSystemFileHandle 文件对象句柄(若拖动的项目是文件)或 FileSystemDirectoryHandle 目录对象句柄(若拖动的项目是一个目录)

js 复制代码
elem.addEventListener("dragover", (e) => {
  e.preventDefault(); // 阻止导航
});
elem.addEventListener("drop", async (e) => {
  e.preventDefault();  // 阻止导航
  // 处理所有条目
  for (const item of e.dataTransfer.items) {
    // 对于文件/目录条目,kind 将是"file"
    if (item.kind === "file") {
      // 得到文件句柄,或者 目录句柄
      const entry = await item.getAsFileSystemHandle();
      if (entry.kind === "file") {
        // 收到的是文件
      } else if (entry.kind === "directory") {
        // 收到的是目录
      }
    }
  }
});

对象句柄

对象句柄由全局方法调用得到的,通过句柄对象能对文件或者目录进行一些操作

文件对象句柄

文件对象句柄FileSystemFileHandle 接口表示一个指向文件的句柄。可通过 window.showOpenFilePicker() 方法来得到文件对象句柄。

方法

以下方法基本都是得到一个Promise对象

读取文件

getFile()返回一个 File 对象。可读取文件内容

js 复制代码
// 打开文件选择器
const [fileHandle] = await window.showOpenFilePicker();

// 获取文件内容
const fileData = await fileHandle.getFile();
fileData.text()  // 得到文本内容

写入文件内容

createWritable()返回的是FileSystemWritableFileStream 文件流对象,可用于写入文件。

js 复制代码
// 打开文件选择器
const [fileHandle] = await window.showOpenFilePicker();

// 创建一个 FileSystemWritableFileStream 用来写入。
const writable = await fileHandle.createWritable();
// 将文件内容写入到流中。
await writable.write("要写入的内容");
// 关闭文件
await writable.close();

文件流对象句柄

FileSystemWritableFileStream 对象是对单个文件进行编辑的一些功能

方法

写入内容

write(),向此文件写入内容,写入到当前指针偏移处

js 复制代码
// 创建一个新句柄,得到文件句柄
const newHandle = await window.showSaveFilePicker();
// 创建一个 FileSystemWritableFileStream 用于写入
const writableStream = await newHandle.createWritable();
// 写入内容,支持ArrayBuffer、TypedArray、DataView、Blob 或字符串
await writableStream.write("This is my file content");
// 关闭文件并将内容写入磁盘
await writableStream.close();

移动指针位置

seek()移动指针位置,以字节为单位

js 复制代码
await writableStream.seek(100s)

修改文件为指定字节大小

truncate()将与流相关的文件修改为指定的字节大小

js 复制代码
await writableStream.truncate(1024);

目录对象句柄

目录对象句柄FileSystemDirectoryHandle,可对目录内的文件进行删除,读取,创建新文件。该句柄可通过window.showDirectoryPicker()全局方法获得

方法

获取目录内某个子目录的句柄

getDirectoryHandle()返回的是FileSystemDirectoryHandle目录对象句柄

js 复制代码
const dirName = "pic"  // 子目录名称
// create 代表,当目录不存在时,自动创建该目录。最后返回该目录的句柄
const dirHandle = currentDirHandle.getDirectoryHandle(dirName, { create: true })

获取目录内某个文件句柄

getFileHandle()方法返回的是FileSystemFileHandle文件对象句柄

js 复制代码
const dirName = "123.txt"  // 文件名称
// create 代表,当目录不存在时,自动创建该文件。最后返回该文件的句柄
const fileHandle = await dirHandle.getFileHandle(name, { create: true });

删除文件或者删除目录

removeEntry()

js 复制代码
// 默认不允许直接删除有文件的文件夹,recursive设置true,代表递归删除子文件
dirHandle.removeEntry('text.txt', { recursive: true });

获取目录内所有子文件句柄

values()

js 复制代码
const dirHandle = await window.showDirectoryPicker(); // 全局方法得到目录句柄
// 迭代获取每个文件句柄
for await (const value of dirHandle.values()) {
  console.log(value);
}

例子demo

读取文件内容

js 复制代码
const dirHandle = await window.showDirectoryPicker({
    readwrite: true,
    startIn: 'desktop'
});  // 打开一个目录,之后可对该目录内所有文件进行操作读取
// 读取该目录中的text.txt文件的内容
const fileBlob = await getFileContents(dirHandle, 'text.txt') 

async function getFileContents(dirHandle, name) {
    const fileHandle = await dirHandle.getFileHandle(name);
    const fileBlob = await fileHandle.getFile();
    const text = fileBlob.text();
    return text;
}

创建文件写入内容

js 复制代码
const dirHandle = await window.showDirectoryPicker({
    readwrite: true,
    startIn: 'desktop'
});  // 打开一个目录,之后可对该目录内所有文件进行操作读取

// 创建文件,写入内容
await createFile(dirHandle, 'text1.txt', "hello word");

async function createFile(dirHandle, name, contents) {
    const newFileHandle = await dirHandle.getFileHandle(name, { create: true });
    const writable = await newFileHandle.createWritable();
    await writable.write(contents);
    await writable.close();
}

重命名文件名

文件系统API本身并未提供修改文件名的方法,但是可以通过一些思路来实现

  1. 读取该文件内的内容
  2. 创建一个新的文件,设置新的文件名,然后将原来的内容写入,最后保存
  3. 删除原来的文件
js 复制代码
// 重命名文件
async function renameFile() {
    // 打开目录,会弹窗用户授权
    const dirHandle = await window.showDirectoryPicker({
        readwrite: true,
        startIn: 'desktop'
    });
    const originName = "text.txt"  // 原文件名
    const newName = "text-ok.txt"  // 新文件名
    // 读取源文件内容
    const fileBlob = await getFileContents(dirHandle, originName)
    // 创建新文件,按新文件名保存
    await createFile(dirHandle, newName, fileBlob);
    // 删除源文件
    dirHandle.removeEntry(originName, { recursive: true });
}
// 创建新文件并写入内容
async function createFile(dirHandle, name, contents) {
    const newFileHandle = await dirHandle.getFileHandle(name, { create: true });
    const writable = await newFileHandle.createWritable();
    await writable.write(contents);
    await writable.close();
}
// 读取文件内容blob
async function getFileContents(dirHandle, name) {
    const fileHandle = await dirHandle.getFileHandle(name);
    const fileBlob = await fileHandle.getFile();
    return fileBlob;
}
相关推荐
阿智@113 分钟前
Node.js 助力前端开发:自动化操作实战
运维·前端·node.js·自动化
m0_7482517232 分钟前
前端入门之VUE--ajax、vuex、router,最后的前端总结
前端·vue.js·ajax
上等猿36 分钟前
Ajax笔记
前端·笔记·ajax
Amo 672938 分钟前
css 编写注意-1-命名约定
前端·css
匹马夕阳43 分钟前
详细对比JS中XMLHttpRequest和fetch的使用
开发语言·javascript·ecmascript
长风清留扬1 小时前
小程序开发实战项目:构建简易待办事项列表
javascript·css·微信小程序·小程序·apache
程序员_三木1 小时前
从 0 到 1 实现鼠标联动粒子动画
javascript·计算机外设·webgl·three.js
点点滴滴的记录1 小时前
Java的CompletableFuture实现原理
java·开发语言·javascript
程序猿online1 小时前
nvm安装使用,控制node版本
开发语言·前端·学习
web Rookie2 小时前
React 中 createContext 和 useContext 的深度应用与优化实战
前端·javascript·react.js