【JS】Web端访问文件夹,模拟网页版VS Code功能

前言

VS Code网页版支持访问并展示文件夹,https://vscode.dev/?vscode-lang=zh-cn,下面研究一下是如何实现的。

问题点

  • 如何打开并选择文件夹
  • 如何得到文件夹中的内容
  • 如何读到某个文件的内容
  • 如何高亮显示代码

实现

1. 打开并选择文件夹

通过showDirectoryPicker打开文件夹,该方法是异步的。

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 id="btn">选择文件夹</button>
  <script>
    btn.onclick = async function () {
      try {
        const handle = await showDirectoryPicker()
        console.log(handle);
      } catch (e) {
        // 用户拒绝浏览器访问文件
      }
    }
  </script>
</body>

</html>

允许浏览器查看文件

showDirectoryPicker会返回一个文件夹的处理句柄

2. 打开并选择文件夹

调用文件夹处理句柄entries方法可以拿到异步迭代器,对此进行循环即可拿到下一个文件的处理句柄

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 id="btn">选择文件夹</button>
  <script>
    btn.onclick = async function () {
      try {
        const handle = await showDirectoryPicker()
        processHandle(handle)
      } catch (e) {
        // 用户拒绝浏览器访问文件
      }
    }

    async function processHandle(handle) {
      // 得到异步迭代器
      const iter = handle.entries()
      for await (const item of iter) {
        console.log(item);
      }
    }
  </script>
</body>

</html>

递归处理,得到根句柄

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 id="btn">选择文件夹</button>
  <script>
    btn.onclick = async function () {
      try {
        const handle = await showDirectoryPicker()
        const root = await processHandle(handle)
        console.log(root);
      } catch (e) {
        // 用户拒绝浏览器访问文件
      }
    }

    async function processHandle(handle) {
      if (handle.kind === 'file') {
        return handle
      }
      handle.children = []
      // 得到异步迭代器
      const iter = handle.entries()
      for await (const item of iter) {
        handle.children.push(await processHandle(item[1])) // 递归确保是文件
      }

      return handle
    }
  </script>
</body>

</html>

3. 读取文件内容

通过getFile得到文件内容

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 id="btn">选择文件夹</button>
  <script>
    btn.onclick = async function () {
      try {
        const handle = await showDirectoryPicker()
        const root = await processHandle(handle)
        const file = await root.children[0].getFile()
        const reader = new FileReader()
        reader.onload = function (e) {
          console.log(e.target.result);
        }
        reader.readAsText(file, 'utf-8')
      } catch (e) {
        // 用户拒绝浏览器访问文件
        console.log(e);
      }
    }

    async function processHandle(handle) {
      if (handle.kind === 'file') {
        return handle
      }
      handle.children = []
      // 得到异步迭代器
      const iter = handle.entries()
      for await (const item of iter) {
        handle.children.push(await processHandle(item[1])) // 递归确保是文件
      }

      return handle
    }
  </script>
</body>

</html>

4. 高亮显示代码

三方库:highlight.js

相关推荐
万邦科技Lafite17 小时前
京东按图搜索京东商品(拍立淘) API (.jd.item_search_img)快速抓取数据
开发语言·前端·数据库·python·电商开放平台·京东开放平台
Never_Satisfied19 小时前
在JavaScript / Node.js / 抖音小游戏中,使用tt.request通信
开发语言·javascript·node.js
爱吃小胖橘19 小时前
Unity资源加载模块全解析
开发语言·unity·c#·游戏引擎
一只小透明啊啊啊啊20 小时前
Java Web 开发的核心组件:Servlet, JSP,Filter,Listener
java·前端·servlet
你的人类朋友20 小时前
设计模式有哪几类?
前端·后端·设计模式
Yeats_Liao21 小时前
Go Web 编程快速入门 10 - 数据库集成与ORM:连接池、查询优化与事务管理
前端·数据库·后端·golang
千里镜宵烛21 小时前
Lua-迭代器
开发语言·junit·lua
啃火龙果的兔子21 小时前
前端八股文react篇
前端·react.js·前端框架
打小就很皮...21 小时前
React 实现 i18next 中英文切换集成
前端·react.js·i18next
拉不动的猪21 小时前
函数组件和异步组件
前端·javascript·面试