文件操作利器:showOpenFilePicker

概述

在传统的前端开发中,处理用户文件一直是个棘手的问题。虽然 <input type="file"> 提供了基本的文件选择功能,但当需要处理整个目录结构时,开发者往往需要借助复杂的后端支持或Electron等桌面框架。showDirectoryPicker() 的出现彻底改变了这一局面,它为Web应用提供了原生的目录访问能力,文件操作体验。

showDirectoryPicker

showDirectoryPicker() 是 File System Access API 的核心方法之一,它允许Web应用通过用户授权的方式访问整个目录结构,而不仅仅是单个文件。这意味着开发者现在可以在浏览器中实现以前只能在桌面应用中才能完成的文件操作。

核心特性

  • 完整的目录访问:读取、遍历、修改目录内容
  • 权限持久化:用户授权后可保存访问权限
  • 安全沙箱:在严格的用户控制下运行
  • 现代化API:基于Promise的异步设计

浏览器支持情况

只有部分浏览器支持,并且版本比较新,希望以后能够更好支持

基础使用与语法

基本调用方式

js 复制代码
async function selectDirectory() {
  try {
    const directoryHandle = await window.showDirectoryPicker();
    console.log('选择的目录:', directoryHandle.name);
    return directoryHandle;
  } catch (err) {
    if (err.name === 'AbortError') {
      console.log('用户取消了选择');
    } else {
      console.error('发生错误:', err);
    }
  }
}

配置选项

js 复制代码
const options = {
  id: 'projectFolder', // 标识符,用于记住用户选择
  mode: 'readwrite',   // 权限模式:read 或 readwrite
  startIn: 'documents' // 起始目录:desktop, documents, downloads等
};

const directoryHandle = await showDirectoryPicker(options);

权限模式

  • read :仅读取权限,可以列出文件和读取内容
  • readwrite :读写权限,可以创建、修改、删除文件

实际应用场景

遍历文件内容

js 复制代码
async function* walkDirectory(directoryHandle, path = '') {
  for await (const entry of directoryHandle.values()) {
    const entryPath = `${path}/${entry.name}`;
    
    if (entry.kind === 'directory') {
      yield* await walkDirectory(entry, entryPath);
    } else {
      yield {
        handle: entry,
        path: entryPath,
        kind: 'file'
      };
    }
  }
}

// 使用示例
async function printDirectoryTree() {
  const directoryHandle = await showDirectoryPicker();
  
  for await (const entry of walkDirectory(directoryHandle)) {
    console.log(entry.path);
  }
}

printDirectoryTree()

解析本地文件夹可视化到线上

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <button>打开文件</button>


    <script>

        const btn = document.querySelector('button');

        btn.addEventListener('click', async () => {
            const fileHandles = await showDirectoryPicker();

            await processHandle(fileHandles);


            console.log("fileHandles----", fileHandles);

            processFile(fileHandles);

            async function processHandle(handle) {
                if (handle.kind === 'file') {
                    return
                }
                const iter = handle.entries();
                handle.children = []
                for await (const [name, childHandle] of iter) {
                    handle.children.push(childHandle);
                    processHandle(childHandle);
                }
            }



            async function processFile(fileHandles) {

                if (fileHandles.kind === 'file') {
                    const file = await fileHandles.getFile();
                    console.log("file----", file);
                    const fileReader = new FileReader();

                    fileReader.onload = (e) => {
                        console.log("fileReader.result---", e.target.result);
                    }

                    fileReader.readAsText(file);
                } else {
                    for (let i = 0; i < fileHandles.children.length; i++) {
                        const childHandle = fileHandles.children[i];
                        processFile(childHandle);
                    }
                }


            }
        });
    </script>
</body>

</html>
相关推荐
zhongjiahao2 分钟前
一文带你了解前端全局状态管理
前端
柳安3 分钟前
对keep-alive的理解,它是如何实现的,具体缓存的是什么?
前端
keyV3 分钟前
告别满屏 v-if:用一个自定义指令搞定 Vue 前端权限控制
前端·vue.js·promise
X_Eartha_8155 分钟前
前端学习—HTML基础语法(1)
前端·学习·html
如果你好5 分钟前
一文搞懂事件冒泡与阻止方法:event.stopPropagation() 实战指南
前端·javascript
用户8168694747259 分钟前
深入 useMemo 与 useCallback 的底层实现
前端·react.js
AAA简单玩转程序设计10 分钟前
救命!Java 进阶居然还在考这些“小儿科”?
java·前端
www_stdio10 分钟前
我的猫终于打上冰球了——一个 Vue3 + Coze AI 项目的完整落地手记
javascript·vue.js·coze
MediaTea18 分钟前
思考与练习(第十章 文件与数据格式化)
java·linux·服务器·前端·javascript
JarvanMo21 分钟前
别用英语和你的大语言模型说话
前端