h5文件上传历史本地持久化与一键重发的核心是仅存元数据(如文件名、大小、fileid、url等)于localstorage或indexeddb,重发时通过fileid调用服务端重传接口或引导用户重新选文件。

在 H5 页面中实现文件上传历史记录的本地持久化与一键重发,核心是:用 localStorage(或 IndexedDB)存上传元数据 + 前端重新构造 FormData 发起请求,不依赖服务端返回的原始文件内容(因为浏览器禁止 JS 直接读取已选文件路径或二进制内容,除非用户再次选择)。
一、只存元数据,不存文件本身
浏览器出于安全限制,JS 无法长期持有 File 对象(页面刷新即失效),也不能读取其绝对路径。因此必须换思路:
- 上传成功后,仅保存关键元信息:文件名、大小、类型、上传时间、服务端返回的唯一 ID(如 file_id)、状态(success)、接口 URL、额外参数(如 folderId)等;
- 不保存 base64 / blob URL / ArrayBuffer —— 占用存储、无实际重发价值,且刷新后失效;
- 如果需预览,可保存服务端返回的可公开访问 URL(如 CDN 链接),用于列表展示。
二、使用 localStorage 管理轻量历史(适合 ≤ 100 条)
对大多数 H5 场景(如表单附件、聊天图片),localStorage 足够用。示例结构:
(JSON 字符串形式存入 key"uploadHistory")
[
{
"id": "u_abc123",
"name": "合同扫描件.pdf",
"size": 2048567,
"type": "application/pdf",
"url": "https://cdn.example.com/files/xyz123.pdf",
"fileId": "srv_f9a8b7c",
"timestamp": 1715823400123,
"status": "success",
"api": "/api/v1/upload",
"params": {"folderId": "fld_5566"}
}
]
操作建议:
- 每次新增记录:
JSON.parse(localStorage.getItem('uploadHistory') || '[]')→ push 新对象 →JSON.stringify→ set 回去; - 删除记录或更新状态(如标记为“重发中”)时同步写入;
- 注意 localStorage 有容量限制(通常 5–10MB),定期清理过期条目(如保留最近 30 天)。
三、一键重发:重建请求,非复用原 File
点击“重发”时,不能直接用旧 File 对象(已不可用)。正确做法是:
- 从历史记录中取出该条目的
fileId和params; - 调用服务端提供的「根据 fileId 快速重传」接口(推荐)——例如
POST /api/v1/resend?fileId=srv_f9a8b7c,服务端直接复用已存文件,返回新 URL 或确认结果; - 若服务端不支持重传接口,则前端需引导用户**再次选择同名文件**(可用
<input type="file" style="display:none">+click()触发),再按常规流程上传 —— 此时可预填文件名、自动勾选、跳过校验提示,提升体验; - 避免尝试用
URL.createObjectURL(file)恢复,因原File已丢失,此法行不通。
四、进阶:用 IndexedDB 存更复杂场景(如带缩略图、断点续传)
当需要存缩略图 blob、分片上传进度、或历史超 500 条时,升级到 IndexedDB:
- 建 objectStore 如
uploadRecords,keyPath 设为id; - 缩略图可存为
blob类型字段(IndexedDB 支持); - 断点信息(如已上传分片列表)也一并序列化存入;
- 仍不存原始大文件,只存元数据 + 服务端地址。
不复杂但容易忽略:所有重发逻辑必须和服务端约定清楚,前端只是触发器,真正复用或再生能力在后端。本地存的永远是“线索”,不是“货物”。











