上传文件到本地
需求背景:在开发静态页面的过程或者一个简单的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>