- 创建统一的下载错误处理模块 (lib/download-errors.ts) - 实现13种错误类型分类和中文错误消息 - 后端统一使用 createDownloadError 创建标准化错误响应 - 前端统一使用 parseDownloadError 解析错误并显示 - 修复正式系统数据库Schema,添加产品全案相关字段和表 - 执行数据库迁移:添加 task_no, task_status, task_fetched_at 字段 - 创建 material_assets, api_keys, api_call_logs 表
3.9 KiB
3.9 KiB
上传状态问题分析报告
📋 问题描述
用户报告正式系统中有4个素材"一直在上传",但实际上传已完成。
🔍 问题分析
系统架构
-
分片上传机制
- 大文件(≥5MB)使用分片上传
- 使用 IndexedDB 存储上传状态
- 上传流程:
chunkUpload→completeUpload→deleteUploadState
-
状态存储
- IndexedDB 数据库名:
chunk-upload-db - ObjectStore 名:
upload-states - 存储内容:文件ID、文件名、分片信息、上传进度等
- IndexedDB 数据库名:
-
状态清理
- 正常情况下,
completeUpload成功后应该调用deleteUploadState清理状态 - 如果出现异常,状态可能残留
- 正常情况下,
可能的原因
-
状态未正确清理
completeUpload成功但deleteUploadState未执行- 上传过程中异常,状态没有正确清理
- 网络问题导致清理请求失败
-
前端显示问题
- IndexedDB 中有残留状态
- 如果使用
ResumeUploadModal,会显示这些残留状态 - 前端可能认为还有未完成的上传
-
实际状态
- ✅ 文件已成功上传到服务器
- ✅ 数据库记录已创建
- ⚠️ 但 IndexedDB 中可能还有残留状态
✅ 验证结果
-
服务器端验证
- ✅ 所有4个素材的文件都已成功上传
- ✅ 数据库记录正常
- ✅ 文件大小正常(1.6GB左右)
-
前端状态
- ⚠️ 需要检查浏览器 IndexedDB 中是否有残留状态
🛠️ 解决方案
方案1:使用检查工具(推荐)
已创建检查工具:scripts/check-indexeddb-uploads.html
使用方法:
- 在浏览器中打开此HTML文件
- 工具会自动检查 IndexedDB 中的上传状态
- 如果发现残留状态:
- 可以单独删除某个状态
- 或者清除所有状态
方案2:手动清理(开发者工具)
- 打开浏览器开发者工具(F12)
- 切换到 Application 标签
- 左侧找到 IndexedDB →
chunk-upload-db→upload-states - 查看是否有残留的状态记录
- 如果有,可以手动删除
方案3:代码修复(长期)
如果问题经常出现,可以考虑:
-
增强错误处理
// 在 completeUpload 成功后,确保删除状态 try { result = await completeUpload(state.uploadId!, metadata) await deleteUploadState(fileId) // 确保执行 return result } catch (error) { // 即使失败也要清理状态(避免残留) await deleteUploadState(fileId).catch(() => {}) throw error } -
添加状态验证
- 上传完成后,验证服务器端是否已创建记录
- 如果已创建,清理本地状态
- 如果未创建,保留状态以便重试
-
定期清理
- 检查超过一定时间(如24小时)的残留状态
- 验证服务器端是否已创建记录
- 如果已创建,自动清理
📝 检查清单
- 在浏览器中打开检查工具查看 IndexedDB 状态
- 确认是否有残留状态
- 如果有,验证服务器端是否已创建记录
- 如果已创建,清理 IndexedDB 中的残留状态
- 刷新页面,确认问题是否解决
🔗 相关文件
lib/chunk-upload.ts- 分片上传核心逻辑components/ResumeUploadModal.tsx- 恢复上传模态框scripts/check-indexeddb-uploads.html- 检查工具app/api/materials/upload/complete/route.ts- 完成上传API
📌 注意事项
-
不要轻易删除状态
- 如果服务器端未创建记录,删除状态会导致无法恢复上传
- 建议先验证服务器端状态再删除
-
IndexedDB 是浏览器本地存储
- 每个浏览器、每个域名独立
- 需要在使用该浏览器的用户端操作
- 不能从服务器端清理
-
如果问题持续出现
- 可能需要检查代码逻辑
- 添加更多的错误处理和日志
- 考虑添加状态同步机制