需求背景:在开发静态页面的过程或者一个简单的demo的时候需要一个上传文件的功能,要求文件能新增、删除、回显、下载等功能;localStorage和sessionStorage虽然能存储一部分信息,但是无法存储file对象文件信息。本文也是也是存储在本地,但是可以如同存储在数据库一样,随意获取file对象数据
demo代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>上传文件到本地</title>
<style>
#uploadBox{
width: 400px;
height: 300px;
margin: auto;
}
/* 上传文件 */
#box {
width: 100%;
height: 150px;
border: 2px dashed #aaa;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer
}
ul {
margin-top: 10px;
padding-left: 20px
}
#examineFile,
#customsFile {
display: none;
}
</style>
</head>
<body>
<div id="uploadBox">
<div id="box">点击或拖拽上传 PDF / 图片</div>
<input id="in" type="file" multiple accept="image/*,application/pdf" style="display:none">
<ul id="ShowFilelist"></ul>
</div>
<script>
/* ---------- 1. 建库(原生) ---------- */
const DB_NAME = 'FileDB';
const STORE = 'files';
const VER = 1;
let db;
const openDB = () => new Promise((resolve, reject) => {
const req = indexedDB.open(DB_NAME, VER);
req.onerror = () => reject(req.error);
req.onsuccess = () => { db = req.result; resolve(); };
req.onupgradeneeded = () => {
const store = req.result.createObjectStore(STORE, { keyPath: 'id', autoIncrement: true });
store.createIndex('name', 'name', { unique: false });
};
});
/* ---------- 2. 工具函数 ---------- */
const addFile = f => new Promise((resolve, reject) => {
const tx = db.transaction([STORE], 'readwrite');
const store = tx.objectStore(STORE);
const req = store.put({ name: f.name, data: f, type: f.type });
req.onsuccess = () => resolve();
req.onerror = () => reject(req.error);
});
const getAll = () => new Promise((resolve, reject) => {
const tx = db.transaction([STORE], 'readonly');
const req = tx.objectStore(STORE).getAll();
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
});
const delFile = id => new Promise((resolve, reject) => {
const tx = db.transaction([STORE], 'readwrite');
const req = tx.objectStore(STORE).delete(id);
req.onsuccess = () => resolve();
req.onerror = () => reject(req.error);
});
/* ---------- 3. 交互 ---------- */
const box = document.getElementById('box');
const inp = document.getElementById('in');
const list = document.getElementById('ShowFilelist');
box.onclick = () => inp.click();
box.ondragover = e => e.preventDefault();
box.ondrop = e => { e.preventDefault(); save([...e.dataTransfer.files]); };
inp.onchange = () => save([...inp.files]);
/* ---------- 4. 保存 & 刷新列表 ---------- */
async function save(files) {
await openDB();
for (const f of files) {
if (!/^(image\/|application\/pdf)/.test(f.type)) continue;
await addFile(f);
}
refresh();
}
async function refresh() {
await openDB();
const fileList = await getAll();
list.innerHTML = '';
console.log("获取所有本地文件", fileList);
fileList.forEach(f => {
const li = document.createElement('li');
li.textContent = f.name;
const btn = document.createElement('button');
btn.textContent = '删除';
btn.className = "ml10"
btn.addEventListener('click', () => del(f.id)); // ✅ 纯 JS 绑定
li.appendChild(btn);
list.appendChild(li);
});
}
async function del(id) { await delFile(id); refresh(); }
refresh(); // 页面加载即显示
</script>
</body>
</html>