純JS實現(xiàn)監(jiān)控本地文件變化
網(wǎng)頁端的超級能力:File System Observer API
在最新的Web技術(shù)革命中,我們迎來了一個令人興奮的新API——File System Observer API(文件系統(tǒng)觀察者API)。這不僅僅是一個簡單的文件操作工具,它賦予了網(wǎng)頁應(yīng)用前所未有的能力——實時監(jiān)控本地文件的一舉一動!
實時監(jiān)控,無需刷新
想象一下,你正在開發(fā)一個Web端相冊應(yīng)用,用戶可以隨時添加或刪除圖片。有了File System Observer API,你的應(yīng)用能夠即時響應(yīng)這些變化,無需用戶手動刷新頁面。這就像是給網(wǎng)頁裝上了千里眼和順風(fēng)耳,任何文件的新增、修改或刪除都逃不過它的監(jiān)控。
實現(xiàn)監(jiān)聽,簡單幾步
實現(xiàn)文件監(jiān)聽的步驟簡單到令人難以置信。首先,你需要實例化一個FileSystemObserver
對象,并傳入一個回調(diào)函數(shù)。然后,通過showOpenFilePicker
或showDirectoryPicker
選擇要監(jiān)聽的文件或文件夾,并使用observe
方法開始監(jiān)聽。
監(jiān)聽文件和文件夾
無論是單個文件還是整個文件夾,F(xiàn)ile System Observer API都能輕松應(yīng)對。你可以選擇監(jiān)聽文件夾的一級內(nèi)容,或者通過設(shè)置recursive: true
來監(jiān)聽所有子級內(nèi)容。
操作類型全覆蓋
文件的新建、刪除、修改、移動,甚至是重命名,F(xiàn)ile System Observer API都能準(zhǔn)確捕捉并通知你的應(yīng)用。每個操作都會生成一個詳細(xì)的FileSystemChangeRecord
對象,讓你能夠精確地了解發(fā)生了什么。
試一下我們的 Demo,實時進行修改,就會觸發(fā)
解除監(jiān)聽,一鍵搞定
當(dāng)你想要停止監(jiān)聽某個文件或文件夾時,只需調(diào)用disconnect
方法,一切都會恢復(fù)原狀。
怎么申請token
首先我們訪問 谷歌FSO申請鏈接 并登錄賬號。
FSO 還是一套嶄新的 API,有多新呢?MDN 和 CanIUse 中還沒有建立關(guān)于它的詞條。但這并不意味著我們完全無法用于生產(chǎn)環(huán)境,我已經(jīng)用到線上功能中了。只要做一點配置工作,你和你的用戶就能成為全球第一批享受到 FSO 的人 。
Chrome 已經(jīng)對 FSO 開啟了試用,版本范圍是 129 到 134,你可以為你的 Web App 域名注冊一個試用 token,你可以跟著我一步一步操作
f12打開控制臺輸入FileSystemObserver
,如果有返回既是使用成功
那怎么調(diào)用這套API來實現(xiàn)我們監(jiān)聽文件夾的功能?
<!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 監(jiān)聽文件夾變化</h1> <div class="alert-box"> <div class="alert-title">?? 注意?。?!</div> <div class="alert-content"> <p>本程序不會上傳任何文件到服務(wù)器,切勿使用重要文件進行調(diào)試,以免造成數(shù)據(jù)丟失</p> </div> </div> <button id="dir-btn">請選擇一個文件夾進行監(jiān)聽</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=`當(dāng)前監(jiān)聽的本地目錄: ${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) }
總結(jié)
File System Observer API的引入,不僅僅是對Web開發(fā)者的一次解放,更是對整個Web生態(tài)的巨大推動。它讓W(xué)eb應(yīng)用更加強大,用戶體驗更加流暢?,F(xiàn)在,是時候開始探索這個全新的API,為你的Web應(yīng)用增添超級能力了!
到此這篇關(guān)于純JS實現(xiàn)監(jiān)控本地文件變化的文章就介紹到這了,更多相關(guān)JS監(jiān)控本地文件變化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解js根據(jù)百度地圖提供經(jīng)緯度計算兩點距離
這篇文章主要介紹了js根據(jù)百度地圖提供經(jīng)緯度計算兩點距離,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05JavaScript 驗證瀏覽器是否支持javascript的方法小結(jié)
一些網(wǎng)站只有客戶端js的驗證,這樣就給一些hacher一些可趁之機了,不信大家測試一些網(wǎng)站的注冊功能看看,有部分網(wǎng)站只有客戶端驗證,我為了達(dá)到客戶端驗證,先是判斷瀏覽器是否支持js,如果不支持,提示信息,然后屏蔽掉發(fā)送按鈕2009-05-05基于BootStrap Metronic開發(fā)框架經(jīng)驗小結(jié)【七】數(shù)據(jù)的導(dǎo)入、導(dǎo)出及附件的查看處理
在很多系統(tǒng)模塊里面,我們可能都需要進行一定的數(shù)據(jù)交換處理,這樣可以很好的達(dá)到用戶操作體驗感,接下來通過本文給大家介紹基于BootStrap Metronic開發(fā)框架經(jīng)驗小結(jié)【七】數(shù)據(jù)的導(dǎo)入、導(dǎo)出及附件的查看處理相關(guān)知識,非常具有參考價值,感興趣的朋友一起學(xué)習(xí)吧2016-05-05淺談html轉(zhuǎn)義及防止javascript注入攻擊的方法
下面小編就為大家?guī)硪黄獪\談html轉(zhuǎn)義及防止javascript注入攻擊的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12async/await實現(xiàn)Promise.acll()簡介
Promise.all() 方法接收一個 promise 的 iterable 類型的輸入,并且只返回一個Promise實例,并且輸入的所有 promise 的 resolve 回調(diào)的結(jié)果是一個數(shù)組,這篇文章主要介紹了async/await實現(xiàn)Promise.acll()簡介,需要的朋友可以參考下2022-11-11Postman參數(shù)化實現(xiàn)過程及原理解析
這篇文章主要介紹了Postman參數(shù)化實現(xiàn)過程及原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08