<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>FileDirectoryStoreManager 测试</title>
<style>
body {
font-family: sans-serif;
margin: 20px;
}
button {
margin: 5px;
padding: 5px 10px;
}
pre {
background: #f0f0f0;
padding: 10px;
}
</style>
</head>
<body>
<h1>FileDirectoryStoreManager 测试</h1>
<button id="openDir">打开目录</button>
<button id="addFile">新增文件</button>
<button id="readFile">读取文件</button>
<button id="updateFile">更新文件</button>
<button id="checkExist">检查文件是否存在</button>
<button id="listKeys">列出所有文件</button>
<button id="removeFile">删除文件</button>
<pre id="output"></pre>
<script>
class FileDirectoryStoreManager {
constructor() {
this.dirHandle = null;
this.dbName = "FileDirectoryStoreDB";
this.storeName = "handles";
this.keyName = "projectDir";
}
_getDB() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, 1);
request.onupgradeneeded = (event) => {
const db = event.target.result;
if (!db.objectStoreNames.contains(this.storeName)) {
db.createObjectStore(this.storeName);
}
};
request.onsuccess = (event) => resolve(event.target.result);
request.onerror = (event) => reject(event.target.error);
});
}
async _saveHandle() {
if (!this.dirHandle) return;
const db = await this._getDB();
const tx = db.transaction(this.storeName, "readwrite");
tx.objectStore(this.storeName).put(this.dirHandle, this.keyName);
return new Promise((resolve, reject) => {
tx.oncomplete = () => resolve(true);
tx.onerror = (e) => reject(e.target.error);
});
}
async _loadHandle() {
const db = await this._getDB();
const tx = db.transaction(this.storeName, "readonly");
const handle = tx.objectStore(this.storeName).get(this.keyName);
return new Promise((resolve) => {
handle.onsuccess = async (e) => {
const dirHandle = e.target.result;
if (!dirHandle) return resolve(null);
let perm = await dirHandle.queryPermission({ mode: "readwrite" });
if (perm === "granted") return resolve(dirHandle);
perm = await dirHandle.requestPermission({ mode: "readwrite" });
if (perm === "granted") return resolve(dirHandle);
resolve(null);
};
handle.onerror = () => resolve(null);
});
}
_assertDir() {
if (!this.dirHandle) throw new Error("Project directory not opened");
}
async openDir() {
this.dirHandle = await this._loadHandle();
if (this.dirHandle) return this.dirHandle;
this.dirHandle = await window.showDirectoryPicker();
await this._saveHandle();
return this.dirHandle;
}
async add(key, fileData) {
this._assertDir();
const fileHandle = await this.dirHandle.getFileHandle(key, {
create: true,
});
const writable = await fileHandle.createWritable();
await writable.write(fileData);
await writable.close();
return true;
}
async read(key) {
this._assertDir();
const fileHandle = await this.dirHandle.getFileHandle(key);
return await fileHandle.getFile();
}
async update(key, fileData) {
return this.add(key, fileData);
}
async remove(key) {
this._assertDir();
await this.dirHandle.removeEntry(key);
return true;
}
async exists(key) {
this._assertDir();
try {
await this.dirHandle.getFileHandle(key);
return true;
} catch {
return false;
}
}
async listKeys() {
this._assertDir();
const keys = [];
for await (const [name, handle] of this.dirHandle.entries()) {
if (handle.kind === "file") keys.push(name);
}
return keys;
}
}
</script>
<script>
const store = new FileDirectoryStoreManager();
const output = document.getElementById("output");
function log(msg) {
console.log(msg);
output.textContent += msg + "\n";
}
document.getElementById("openDir").onclick = async () => {
try {
await store.openDir();
log("✅ 已打开目录");
} catch (err) {
log("❌ 打开目录失败: " + err);
}
};
document.getElementById("addFile").onclick = async () => {
try {
const blob = new Blob(["Hello world"], { type: "text/plain" });
await store.add("myfile1.txt", blob);
log("✅ 已新增文件 myfile1.txt");
} catch (err) {
log("❌ 新增文件失败: " + err);
}
};
document.getElementById("readFile").onclick = async () => {
try {
const file = await store.read("myfile1.txt");
const text = await file.text();
log(`📖 文件内容: ${text}`);
} catch (err) {
log("❌ 读取文件失败: " + err);
}
};
document.getElementById("updateFile").onclick = async () => {
try {
const blob = new Blob(["Updated content"], { type: "text/plain" });
await store.update("myfile1.txt", blob);
log("✏️ 已更新文件 myfile1.txt");
} catch (err) {
log("❌ 更新文件失败: " + err);
}
};
document.getElementById("checkExist").onclick = async () => {
try {
const exists = await store.exists("myfile1.txt");
log(`🔍 文件是否存在: ${exists}`);
} catch (err) {
log("❌ 检查存在失败: " + err);
}
};
document.getElementById("listKeys").onclick = async () => {
try {
const keys = await store.listKeys();
log("🗂️ 所有文件: " + keys.join(", "));
} catch (err) {
log("❌ 列出文件失败: " + err);
}
};
document.getElementById("removeFile").onclick = async () => {
try {
await store.remove("myfile1.txt");
log("🗑️ 已删除文件 myfile1.txt");
} catch (err) {
log("❌ 删除文件失败: " + err);
}
};
</script>
</body>
</html>