localStorage是Web Storage API的一部分,它允许在用户的浏览器中存储键值对数据,具有以下特点:
// 存储文件或文件夹信息
function saveToLocalStorage(key, data) {
try {
const jsonString = JSON.stringify(data);
localStorage.setItem(key, jsonString);
return true;
} catch (e) {
console.error('存储失败:', e);
return false;
}
}
// 读取文件或文件夹信息
function getFromLocalStorage(key) {
try {
const jsonString = localStorage.getItem(key);
return jsonString ? JSON.parse(jsonString) : null;
} catch (e) {
console.error('读取失败:', e);
return null;
}
}
// 文件对象结构示例
const fileInfo = {
name: 'example.txt',
type: 'text/plain',
size: 1024, // 字节
lastModified: Date.now(),
content: '这是文件内容...' // 或者存储Base64编码的内容
};
// 存储文件
saveToLocalStorage('file_example', fileInfo);
// 读取文件
const retrievedFile = getFromLocalStorage('file_example');
console.log(retrievedFile);
// 文件夹结构示例
const folderStructure = {
name: 'My Documents',
type: 'folder',
children: [
{
name: 'Work',
type: 'folder',
children: [
{
name: 'report.pdf',
type: 'application/pdf',
size: 204800
}
]
},
{
name: 'Personal',
type: 'folder',
children: [
{
name: 'photo.jpg',
type: 'image/jpeg',
size: 153600
}
]
}
]
};
// 存储文件夹结构
saveToLocalStorage('folder_structure', folderStructure);
// 读取文件夹结构
const retrievedFolder = getFromLocalStorage('folder_structure');
console.log(retrievedFolder);
原因:localStorage有大小限制(通常5MB)
解决方案:
// 检查剩余空间
function getRemainingSpace() {
let total = '';
for (let i = 0; i < 1024; i++) {
total += '01234567890123456789012345678901234567890';
}
total += '1234567890123456789012345678901234567890';
try {
localStorage.removeItem('test');
localStorage.setItem('test', total);
} catch (e) {
const max = 1024 * 50 + 40;
return (max - total.length) / 1024;
}
return Infinity;
}
原因:localStorage只能存储字符串
解决方案:使用JSON序列化和反序列化
// 安全地存储和读取
function safeSet(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value));
return true;
} catch (e) {
return false;
}
}
function safeGet(key) {
try {
return JSON.parse(localStorage.getItem(key));
} catch (e) {
return null;
}
}
原因:localStorage变化不会自动同步到其他标签页
解决方案:监听storage事件
// 在其他标签页监听变化
window.addEventListener('storage', function(event) {
console.log('存储变化:', event.key, '从', event.oldValue, '变为', event.newValue);
});
// 读取文件并存储
function readAndStoreFile(file) {
return new Promise((resolve, reject) => {
if (file.size > 1 * 1024 * 1024) { // 限制1MB
reject(new Error('文件太大'));
return;
}
const reader = new FileReader();
reader.onload = function(e) {
const fileData = {
name: file.name,
type: file.type,
size: file.size,
lastModified: file.lastModified,
content: e.target.result
};
if (saveToLocalStorage('file_' + file.name, fileData)) {
resolve();
} else {
reject(new Error('存储失败'));
}
};
reader.onerror = reject;
reader.readAsDataURL(file); // 或者使用readAsText/text
});
}
// 递归处理文件夹结构
async function processDirectory(entry, parentPath = '') {
const path = parentPath ? `${parentPath}/${entry.name}` : entry.name;
if (entry.isFile) {
return new Promise(resolve => {
entry.file(file => {
resolve({
name: file.name,
type: file.type,
size: file.size,
lastModified: file.lastModified,
path: path
});
});
});
} else if (entry.isDirectory) {
const dirReader = entry.createReader();
const entries = await new Promise(resolve => {
dirReader.readEntries(resolve);
});
const children = await Promise.all(
entries.map(child => processDirectory(child, path))
);
return {
name: entry.name,
type: 'directory',
path: path,
children: children
};
}
}
// 使用示例(需要用户通过文件选择器选择目录)
document.getElementById('dir-selector').addEventListener('change', async function(e) {
const entries = e.target.files;
if (entries.length) {
const structure = await processDirectory(entries[0]);
saveToLocalStorage('directory_structure', structure);
}
});
// 实现简单的LRU缓存
class LocalStorageLRU {
constructor(maxSize = 5 * 1024 * 1024) {
this.maxSize = maxSize;
this.keys = JSON.parse(localStorage.getItem('_lru_keys') || '[]');
}
setItem(key, value) {
// 计算新数据大小
const newItemSize = JSON.stringify({key, value}).length;
// 检查并清理空间
this._makeSpace(newItemSize);
// 存储数据
localStorage.setItem(key, JSON.stringify(value));
// 更新LRU列表
this._updateKeyAccess(key);
}
getItem(key) {
const value = JSON.parse(localStorage.getItem(key));
if (value !== null) {
this._updateKeyAccess(key);
}
return value;
}
_updateKeyAccess(key) {
// 移除现有key(如果存在)
this.keys = this.keys.filter(k => k !== key);
// 添加到最前面
this.keys.unshift(key);
// 保存keys列表
localStorage.setItem('_lru_keys', JSON.stringify(this.keys));
}
_makeSpace(requiredSize) {
let currentSize = this._calculateTotalSize();
// 从最久未使用的开始删除
while (currentSize + requiredSize > this.maxSize && this.keys.length > 0) {
const oldestKey = this.keys.pop();
const itemSize = localStorage.getItem(oldestKey).length;
localStorage.removeItem(oldestKey);
currentSize -= itemSize;
}
localStorage.setItem('_lru_keys', JSON.stringify(this.keys));
}
_calculateTotalSize() {
return Object.keys(localStorage).reduce((total, key) => {
if (key !== '_lru_keys') {
total += localStorage.getItem(key).length;
}
return total;
}, 0);
}
}
// 使用示例
const lruCache = new LocalStorageLRU(2 * 1024 * 1024); // 2MB限制
lruCache.setItem('file1', fileInfo1);
lruCache.setItem('file2', fileInfo2);
const file = lruCache.getItem('file1');
使用localStorage存储文件和文件夹信息是一种简单有效的客户端数据持久化方案,适合小型应用和临时数据存储。对于更复杂的需求或更大的数据量,建议考虑IndexedDB或其他客户端存储方案。