浏览器读写本地文件

安全上下文

API 仅在 安全上下文 (HTTPS) 中可用,在某些或所有支持浏览器中可用。

文件系统访问 API (File System Access API) 允许与用户本地设备或用户可访问的网络文件系统上的文件进行交互。此 API 的核心功能包括读取文件、写入或保存文件以及对目录结构的访问。

打开文件

语法

showOpenFilePicker();

参数:

options 可选参数

multiple 布尔值;是否多选. 默认 false.

excludeAcceptAllOption 布尔值;是否排除接受所有选项. 默认 false.

types 数组;指定文件类型.

示例

// 选择文件
const openFile = (multiple = false) => {
  window
    .showOpenFilePicker({
      multiple: multiple, // 多选
      excludeAcceptAllOption: true,
      types: [
        {
          description: "选择图片",
          accept: {
            "image/*": [".png", ".gif", ".jpeg", ".jpg"],
          },
        },
      ],
    })
    .then((fileHandles) => {
      console.log(fileHandles);
      let files = fileHandles
        .map((fileHandle) => fileHandle.name || "")
        .join("\n");
      console.log(`选择了 ${fileHandles.length} 个文件: \n${files}`);
    })
    .catch((err) => {
      console.log("选择文件失败:", err);
    });
};

// 查看文本文件内容
const openTextFile = () => {
  window
    .showOpenFilePicker({
      multiple: false, // 取消多选
      excludeAcceptAllOption: true,
      types: [
        {
          description: "选择文本文件",
          accept: {
            "text/plain": [".txt"],
          },
        },
      ],
    })
    .then((fileHandles) => {
      const [fh] = fileHandles;
      // console.log(fh);
      fh.getFile().then((file) => {
        console.log("file:", file);
        // 读取文本内容
        const reader = new FileReader();
        reader.onload = (e) => {
          console.log(
            `打开文件: ${fh.name}\n文件内容:\n\n%c${e.target.result}`,
            "color:#35ccbf;fontsize: 20px;"
          );
        };
        reader.readAsText(file);
      });
    })
    .catch((err) => {
      console.error("选择文件失败: ", err);
    });
};

写入文件

语法

showSaveFilePicker();

参数

options 可选参数

excludeAcceptAllOption 布尔值;是否排除接受所有选项. 默认 false.

suggestedName 字符串. 建议的文件名.

types 数组;指定文件类型.

示例

// 写入文本内容到文本文件
window
  .showSaveFilePicker({
    suggestedName: "写入测试.txt", // 待写入的文件名
  })
  .then(async (writeHandle) => {
    // create a FileSystemWritableFileStream to write to
    const writableStream = await writeHandle.createWritable();

    /* writableStream.write 的可选参数
      // just pass in the data (no options)
      writableStream.write(data);

      // writes the data to the stream from the determined position
      writableStream.write({ type: "write", position, data });

      // updates the current file cursor offset to the position specified
      writableStream.write({ type: "seek", position });

      // resizes the file to be size bytes long
      writableStream.write({ type: "truncate", size });
      */

    // 写入文件
    await writableStream.write("这里是要写入的文本内容\n换一行吧\n\n再写一行");

    // close the file and write the contents to disk.
    await writableStream.close();
    console.log(`保存成功: ${writeHandle.name}`);
  })
  .catch((err) => {
    console.error("写入失败: ", err);
  });

打开目录

语法

const FileSystemDirectoryHandle = await window.showDirectoryPicker();

参数

options 可选参数

id 通过指定 ID,浏览器可以记住不同 ID 的不同目录。如果将同一 ID 用于另一个选取器,则该选取器将在同一目录中打开。

mode "read","readwrite",默认为只读访问。

startIn 打开目录时的起始位置,可以是一个 FileSystemHandle 或者一个众所周知的目录如: ("desktop", "documents", "downloads", "music", "pictures", or "videos")。

示例

// 选择目录
window
  .showDirectoryPicker({
    // id: "firstDir",
    mode: "read", // "read" 或 "readwrite", 默认只读
    /**
     * 起始位置, 常见的如 "desktop", "documents", "downloads",
     * "music", "pictures", or "videos" 等用户目录,
     * 或者一个 FileSystemHandle 对象
     */
    startIn: "downloads",
  })
  .then(async (dirHandle) => {
    console.log(dirHandle);
    let files = [];
    for await (const [key, value] of dirHandle.entries()) {
      files.push(key);
    }
    console.log(
      `打开目录: ${dirHandle.name}\n` + `文件列表: \n${files.join("\n")}`
    );
  })
  .catch((err) => {
    console.error("打开目录失败: ", err);
  });

参考资料

  1. 浏览器读写本地文件 File System Access API
  2. showOpenFilePicker
  3. showSaveFilePicker
  4. showDirectoryPicker