it编程 > 编程语言 > Javascript

纯JS实现监控本地文件变化

9人参与 2025-04-24 Javascript

网页端的超级能力:file system observer api

在最新的web技术革命中,我们迎来了一个令人兴奋的新api——file system observer api(文件系统观察者api)。这不仅仅是一个简单的文件操作工具,它赋予了网页应用前所未有的能力——实时监控本地文件的一举一动!

实时监控,无需刷新

想象一下,你正在开发一个web端相册应用,用户可以随时添加或删除图片。有了file system observer api,你的应用能够即时响应这些变化,无需用户手动刷新页面。这就像是给网页装上了千里眼和顺风耳,任何文件的新增、修改或删除都逃不过它的监控。

实现监听,简单几步

实现文件监听的步骤简单到令人难以置信。首先,你需要实例化一个filesystemobserver对象,并传入一个回调函数。然后,通过showopenfilepickershowdirectorypicker选择要监听的文件或文件夹,并使用observe方法开始监听。

监听文件和文件夹

无论是单个文件还是整个文件夹,file system observer api都能轻松应对。你可以选择监听文件夹的一级内容,或者通过设置recursive: true来监听所有子级内容。

操作类型全覆盖

文件的新建、删除、修改、移动,甚至是重命名,file system observer api都能准确捕捉并通知你的应用。每个操作都会生成一个详细的filesystemchangerecord对象,让你能够精确地了解发生了什么。

试一下我们的 demo,实时进行修改,就会触发

解除监听,一键搞定

当你想要停止监听某个文件或文件夹时,只需调用disconnect方法,一切都会恢复原状。

怎么申请token

首先我们访问 谷歌fso申请链接 并登录账号。

fso 还是一套崭新的 api,有多新呢?mdn 和 caniuse 中还没有建立关于它的词条。但这并不意味着我们完全无法用于生产环境,我已经用到线上功能中了。只要做一点配置工作,你和你的用户就能成为全球第一批享受到 fso 的人 。

chrome 已经对 fso 开启了试用,版本范围是 129 到 134,你可以为你的 web app 域名注册一个试用 token,你可以跟着我一步一步操作

f12打开控制台输入filesystemobserver,如果有返回既是使用成功

那怎么调用这套api来实现我们监听文件夹的功能?

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>谷歌fso api</title>
  <style>
    .row-box {
      display: flex;
    }
    .row-box > div {
      width: 50%;
      height: 70vh;
      overflow: auto;
    }
    #log-box {
      background-color: #f0f0f0;
      padding: 10px;
      border: 1px solid #ccc;
      border-radius: 5px;
      display: none;
    }
    .alert-box {
      color: red;
      font-size: 12px;
      line-height: 1;
      margin-bottom: 12px;
      padding: 8px;
      border-radius: 12px;
    }
    .alert-title,.alert-content{
      font-size: 20px;
    }
    #dir-name{
      color: red;
    }
  </style>
</head>
<body>
  <h1>file observer api 监听文件夹变化</h1>
  <div class="alert-box">
    <div class="alert-title">⚠️ 注意!!!</div>
    <div class="alert-content">
      <p>本程序不会上传任何文件到服务器,切勿使用重要文件进行调试,以免造成数据丢失</p>
    </div>
  </div>
  <button id="dir-btn">请选择一个文件夹进行监听</button>
  <p>
    <span id="dir-name"></span>
  </p>
  <div class="row-box">
    <div id="dir-info"></div>
    <div id="log-box"></div>
  </div>
  <script type="importmap">
  {
    "imports": {
      "@rejax/fsot": "https://unpkg.com/@rejax/fsot/index.js"
    }
  }
  </script>
  <script type="module">
    import { setfsobservertoken } from './index.js'
    setfsobservertoken()
  </script>
  <script type="module">
    import { fsobserver } from '@rejax/fsot'

    const dirbtn = document.getelementbyid('dir-btn')
    const dirinfo = document.getelementbyid('dir-info')
    const logbox = document.getelementbyid('log-box')
    const dirname = document.getelementbyid('dir-name')

    let direntries = null
    const fob = new fsobserver(callback)

    const kindmap = {
      'directory': '文件夹',
      'file': '文件',
    }
    const operationmap = {
      'appeared': '新增',
      'disappeared': '删除',
      'modified': '修改',
      'moved': '移动',
      'renamed': '重命名',
    }
    
    dirbtn.addeventlistener('click', handleclick)
    
    async function handleclick() {
      const dirhandle = await window.showdirectorypicker()
      direntries = dirhandle.values()

      const options = {
        recursive: true,
      }
      
      console.log('fob', fob);
      
      await fob.observe(dirhandle, options)
      const localdirname = fob.roothandle.name
      dirname.innertext=`当前监听的本地目录: ${localdirname}`

      dirbtn.disabled = true
      logbox.style.display = 'block'

      for await (const entry of direntries) {
        const { kind, name } = entry
        showchild(kind, name)
      }
    }
    
    async function callback(log, records, observer) {
      console.log('log', log);
      const logele = document.createelement('p')
      logele.innertext = log.description
      logbox.appendchild(logele)

      const { operation, handle, to, from } = log
      switch (operation) {
        case 'create':
          add(handle, to)
          break
        case 'remove':
          remove(handle, to)
          break
        case 'modify':
          modifyfile(handle, to)
          break
        case 'move':
          move(handle, to, from)
          break
        case 'rename':
          rename(handle, to, from)
          break
      }
    }
    function showchild(kind, name) {
      const entryid = `${kind}-${name}`
      const entry = document.createelement('p')
      entry.id = entryid
      entry.innerhtml = `${kindmap[kind]} ${name}`
      dirinfo.appendchild(entry)
    }
    
    async function add(handle, path) {
      const { kind } = handle
      if (!path.includes('/')) {
        // 子文件中增加实体时,不显示
        showchild(kind, path)
      }
    }

    function remove(handle, path) {
      const { kind, name } = handle
      const childname = path || name
      const entryid = `${kind}-${childname}`
      const entry = document.getelementbyid(entryid)
      if (entry) {
        entry.remove()
      }
    }

    async function modifyfile(handle, path) {
      
    }

    async function rename(handle, path, oldpath) {
      const { kind, name } = handle
      const childname = path || name
      const entryid = `${kind}-${oldpath}`
      let entry = document.getelementbyid(entryid)
      if (entry) {
        entry.innertext = `${kindmap[kind]} ${path}`
        entry.id = `${kind}-${path}`
      }
    }

    async function move(handle, path, oldpath) {
      const { kind, name } = handle
      const childname = path || name
      const entryid = `${kind}-${oldpath}`
      let entry = document.getelementbyid(entryid)
      const patharr = path.split('/')
      const oldpatharr = oldpath.split('/')
      
      // 文件层级下沉
      if (patharr.length > oldpatharr.length) {
        entry?.remove()
      }

      // 文件层级上升
      if (patharr.length < oldpatharr.length && patharr.length === 1) {
        showchild(kind, name)
      }
    }
  </script>
</body>
</html>

这里是setfsobservertoken,把前面申请到的token进行替换即可,这里要配置好域名,域名不一样会报错,无法使用

export function setfsobservertoken () {
  let token = 'avbwevroc6h+jsr2r1nwgj0g0t8tos2mnxt9gsfchvxv2un4gq/+9sa2tfwbjghubze5lyf+apspjovp+ntneqwaaabweyjvcmlnaw4ioijodhrwoi8vmti3ljaumc4xojuzmta1iiwizmvhdhvyzsi6ikzpbgvtexn0zw1pynnlcnzlciisimv4cglyesi6mtc0nze4mdc5ox'
  const origin = window.location.origin
  if (origin.includes('https://rejax.fun')) {
    token = 'avbwevroc6h+jsr2r1nwgj0g0t8tos2mnxt9gsfchvxv2un4gq/+9sa2tfwbjghubze5lyf+apspjovp+ntneqwaaabweyjvcmlnaw4ioijodhrwoi8vmti3ljaumc4xojuzmta1iiwizmvhdhvyzsi6ikzpbgvtexn0zw1pynnlcnzlciisimv4cglyesi6mtc0nze4mdc5ox'
  }
  const meta = document.createelement('meta')
  meta.httpequiv = 'origin-trial'
  meta.content = token
  document.head.appendchild(meta)
}

总结

file system observer api的引入,不仅仅是对web开发者的一次解放,更是对整个web生态的巨大推动。它让web应用更加强大,用户体验更加流畅。现在,是时候开始探索这个全新的api,为你的web应用增添超级能力了!

到此这篇关于纯js实现监控本地文件变化的文章就介绍到这了,更多相关js监控本地文件变化内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

JavaScript 获取 URL 中参数值的方法详解(最新整理)

04-24

VS Code中搭建JavaScript运行环境超详细过程

04-24

JavaScript双问号操作符(??)详解及如何解决使用||时因类型转换带来的问题

04-24

鸿蒙系统中实现图片上传功能全流程

04-24

JavaScript中实现Sleep功能及其应用的几种方法

04-24

微信小程序事件绑定基本语法示例详解

04-24

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论