9.1 KiB
9.1 KiB
修复 localStorage 配额超出问题 v3.14.2.2
📋 版本信息
- 版本号: v3.14.2.2
- 修复日期: 2025-01-12
- 影响范围: 所有文件上传方式
- 严重程度: 🔴 紧急 - 导致批量上传失败
🐛 问题描述
用户在批量上传 bin 文件时遇到以下错误:
QuotaExceededError: Failed to execute 'setItem' on 'Storage':
Setting the value of 'gameTokens' exceeded the quota.
现象:
- 文件夹批量上传 36 个 bin 文件,前 34 个成功,后续全部失败
- 压缩包上传也遇到类似问题
- 即使成功上传的 Token 也无法保存到 localStorage
影响:
- ❌ 无法批量导入大量 Token
- ❌ 导入的 Token 无法持久化
- ❌ 页面刷新后丢失数据
🔍 问题根因分析
localStorage 的限制
浏览器的 localStorage 容量限制通常为:
- 大多数浏览器:5MB
- 部分浏览器:10MB
数据重复存储
在 v3.14.2.1 修复 binFileContent 保存问题时,引入了数据重复存储的问题:
// ❌ 错误做法:数据被存储了两次!
// 第1次:tokenStore.importBase64Token 保存
tokenStore.importBase64Token(tokenInfo.name, tokenInfo.token, {
binFileContent: tokenInfo.binFileContent, // ArrayBuffer,几十 KB
binFileId: tokenInfo.binFileId,
rawData: tokenInfo.rawData,
...
})
// 第2次:localTokenStore.addGameToken 又保存一次
const roleId = `role_${Date.now()}_${Math.floor(Math.random() * 1000)}`
localTokenStore.addGameToken(roleId, tokenInfo) // ❌ 包含完整的 tokenInfo,包括 binFileContent!
存储空间计算
假设:
- 每个 bin 文件的 ArrayBuffer:50KB
- 每个 Token 的其他信息(token、wsUrl、rawData 等):5KB
- 重复存储两次:110KB / Token
结果:
- 上传 50 个 Token:50 × 110KB = 5.5MB → 超出 5MB 限制 ❌
- 上传 90 个 Token:90 × 110KB = 9.9MB → 超出 10MB 限制 ❌
🎯 为什么会重复存储?
v3.14.2.1 的修复逻辑
为了解决重连问题,我在 v3.14.2.1 中:
- ✅ 添加了
binFileContent到 tokenInfo - ✅ 改用
tokenStore.importBase64Token保存 - ❌ 错误地添加了
localTokenStore.addGameToken调用
localTokenStore 的作用
localTokenStore 是历史遗留代码,用于:
- 兼容旧版本的 TokenManager 组件
- 提供额外的 Token 管理接口
但它不是必需的!tokenStore 已经提供了所有必要的功能。
✅ 解决方案
核心策略
移除多余的 localTokenStore.addGameToken 调用
修复前的代码(❌ 错误)
// 批量上传、文件夹上传、压缩包上传、bin文件上传
const importResult = tokenStore.importBase64Token(
tokenInfo.name,
tokenInfo.token,
{
server: tokenInfo.server,
wsUrl: tokenInfo.wsUrl,
importMethod: 'bin',
binFileContent: tokenInfo.binFileContent,
binFileId: tokenInfo.binFileId,
rawData: tokenInfo.rawData,
lastRefreshed: tokenInfo.lastRefreshed
}
)
if (!importResult.success) {
throw new Error(importResult.error)
}
// ❌ 重复存储!
const roleId = `role_${Date.now()}_${Math.floor(Math.random() * 1000)}`
localTokenStore.addGameToken(roleId, tokenInfo)
successCount++
uploadProgress.successCount = successCount
修复后的代码(✅ 正确)
// 批量上传、文件夹上传、压缩包上传、bin文件上传
const importResult = tokenStore.importBase64Token(
tokenInfo.name,
tokenInfo.token,
{
server: tokenInfo.server,
wsUrl: tokenInfo.wsUrl,
importMethod: 'bin',
binFileContent: tokenInfo.binFileContent,
binFileId: tokenInfo.binFileId,
rawData: tokenInfo.rawData,
lastRefreshed: tokenInfo.lastRefreshed
}
)
if (!importResult.success) {
throw new Error(importResult.error)
}
// ✅ 移除了 localTokenStore.addGameToken 调用
successCount++
uploadProgress.successCount = successCount
📝 具体修改
修改的文件位置
| 上传方式 | 文件位置 | 修改内容 |
|---|---|---|
| 手机端批量上传 | src/views/TokenImport.vue:1856-1861 |
移除 localTokenStore.addGameToken |
| 文件夹批量上传 | src/views/TokenImport.vue:1997-2002 |
移除 localTokenStore.addGameToken |
| bin文件上传 | src/views/TokenImport.vue:2345-2350 |
移除 localTokenStore.addGameToken |
| 压缩包上传 | src/views/TokenImport.vue:2527-2532 |
移除 localTokenStore.addGameToken |
移除的代码(所有上传方式)
if (!importResult.success) {
throw new Error(importResult.error)
}
- const roleId = `role_${Date.now()}_${Math.floor(Math.random() * 1000)}`
- localTokenStore.addGameToken(roleId, tokenInfo)
-
successCount++
uploadProgress.successCount = successCount
📊 修复效果
存储空间对比
| 项目 | 修复前 | 修复后 | 节省 |
|---|---|---|---|
| 每个 Token 存储 | 110KB | 55KB | 50% ↓ |
| 50 个 Token | 5.5MB ❌ | 2.75MB ✅ | 50% ↓ |
| 90 个 Token | 9.9MB ❌ | 4.95MB ✅ | 50% ↓ |
| 180 个 Token | 19.8MB ❌ | 9.9MB ⚠️ | 50% ↓ |
可上传的 Token 数量
| localStorage 限制 | 修复前 | 修复后 | 提升 |
|---|---|---|---|
| 5MB | ~45 个 | ~90 个 | 2x 🚀 |
| 10MB | ~90 个 | ~180 个 | 2x 🚀 |
🎯 为什么这个修复是安全的?
1. tokenStore 已经保存了所有必要信息
tokenStore.importBase64Token 保存了:
- ✅ Token 字符串
- ✅ WSS 连接地址
- ✅ binFileContent(用于重连)
- ✅ binFileId(用于管理)
- ✅ rawData(原始Token数据)
这些信息已经完全足够支持所有功能:
- WSS 连接
- Token 刷新
- 重新建立连接
2. localTokenStore 是历史遗留
localTokenStore 的主要用途:
- 为旧版本 TokenManager.vue 提供接口
- 提供一些额外的 Token 管理方法
但这些功能都可以通过 tokenStore 实现,不需要重复存储。
3. 不影响现有功能
移除 localTokenStore.addGameToken 调用不会影响:
- ✅ Token 列表显示
- ✅ WSS 连接
- ✅ Token 刷新
- ✅ 重新建立连接
- ✅ 批量任务执行
🚨 后续优化建议
短期方案(已实施)
✅ 移除重复存储 - 立即释放 50% 空间
中期方案(建议)
-
使用 IndexedDB 替代 localStorage
- IndexedDB 支持更大的存储空间(通常几百 MB)
- 适合存储大量二进制数据
-
压缩 binFileContent
- 使用
pako或lz-string压缩 ArrayBuffer - 预期可以节省 30-50% 空间
- 使用
-
按需加载 binFileContent
- 不在 Token 列表中存储 binFileContent
- 只在需要刷新 Token 时从
storedBinFiles加载
长期方案(可选)
-
云端存储 bin 文件
- 将 bin 文件上传到云端服务器
- 本地只保存引用 ID
- 需要时从服务器下载
-
分层存储策略
- 热数据(常用 Token):存储在 localStorage
- 冷数据(不常用 Token):存储在 IndexedDB
- 自动根据使用频率迁移
🧪 测试验证
测试场景
- ✅ 批量上传 50 个 Token → 验证不会超出配额
- ✅ 批量上传 100 个 Token → 验证在 10MB 限制内
- ✅ Token 重连功能 → 验证 binFileContent 可用
- ✅ 页面刷新 → 验证 Token 持久化
预期结果
- ✅ 50 个 Token 顺利上传(原来在 5MB 浏览器上失败)
- ✅ 100 个 Token 顺利上传(原来在 10MB 浏览器上失败)
- ✅ Token 刷新功能正常
- ✅ 页面刷新后 Token 仍然存在
📈 性能影响
正面影响
- ✅ 存储空间减少 50% → 可以存储更多 Token
- ✅ localStorage 读写次数减半 → 性能提升
- ✅ 内存占用减少 → 浏览器更流畅
无负面影响
- ✅ 所有功能保持正常
- ✅ Token 管理不受影响
- ✅ 重连功能依然可用
🎉 总结
问题
- ❌ localStorage 配额超出
- ❌ 批量上传失败
- ❌ 数据重复存储
解决方案
- ✅ 移除
localTokenStore.addGameToken调用 - ✅ 避免数据重复存储
效果
- ✅ 存储空间减少 50%
- ✅ 可上传 Token 数量翻倍(45 → 90,90 → 180)
- ✅ 所有功能保持正常
现在用户可以批量上传更多 Token,不再受到 localStorage 配额的限制!🚀
⚠️ 重要提醒
如果用户需要上传超过 180 个 Token,建议:
- 分批上传 - 每次上传 50-100 个
- 清理旧 Token - 删除不再使用的 Token
- 使用 IndexedDB - 未来版本将支持更大容量存储
- 定期清理 localStorage - 删除不必要的数据
📚 相关文档
修复批量上传binFileContent保存问题v3.14.2.1.md- 引入重复存储问题并发上传全面实施完成v3.14.2.md- 并发上传优化文件批量上传即时保存优化v3.14.1.md- 立即保存优化
版本: v3.14.2.2
状态: ✅ 已修复
优先级: 🔴 紧急