【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

相关推荐
dorisrv1 分钟前
React 状态管理:Zustand 快速上手指南
前端·react.js
lenkco7 分钟前
修改QtConcurrent::run支持任意参数
开发语言·c++·qt
lkbhua莱克瓦249 分钟前
IO流——打印流
java·开发语言·前端·学习方法
im_AMBER13 分钟前
Canvas架构手记 08 CSS Transform | CSS 显示模型 | React.memo
前端·css·笔记·学习·架构
申阳17 分钟前
Day 23:登录设计的本质:从XSS/CSRF到Session回归的技术演进
前端·后端·程序员
赵得C18 分钟前
软件设计师前沿考点精讲:新兴技术与性能优化实战
java·开发语言·分布式·算法·设计模式·性能优化
岛风风20 分钟前
前端HTML导出PDF分页难题:10天踩坑后的终极方案,精细到每个像素点!!!
前端·javascript
LYFlied23 分钟前
单页应用与多页应用:架构选择与前端演进
前端·架构·spa·mpa·ssr
前端老宋Running25 分钟前
你的组件 API 为什么像个垃圾场?—— React 复合组件模式 (Compound Components) 实战教学
前端·react.js·架构
alanAltman26 分钟前
前端架构范式:意图系统构建web
前端·javascript