H5大文件上传崩溃主因是浏览器内存超限,须分片上传、禁用全量读取、规避预览渲染、增强容错降级。

直接在浏览器内存里加载整个大文件,是 H5 上传崩溃的主因。关键不是“传不传得上去”,而是“别让浏览器扛着它走”。核心思路是:不让文件全量进 JS 内存,也不依赖单次读取或渲染。
限制前端一次性处理的数据量
浏览器对单页 JS 堆内存有硬限制(移动端常仅 300–500MB),一旦 file.getBytes() 或 FileReader.readAsArrayBuffer() 加载一个 200MB 文件,几乎必然触发 OOM。必须绕过全量读取:
- 用
file.slice()分块,每次只处理几 MB(如 2–5MB); - 避免调用
file.arrayBuffer()或file.text()——它们会强制全量解码; - 上传前校验大小:
if (file.size > 100 * 1024 * 1024) { alert('文件不能超过 100MB'); return; }; - 禁用多选批量上传高风险场景,或对多文件做串行/限并发(如最多同时处理 2 个)。
用流式分片 + 后端配合上传
分片不是可选项,而是必选项。它把大文件切成小块,每块独立上传、独立校验,失败可重传,且全程不拼接完整二进制:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 前端按字节偏移切片:
const chunk = file.slice(start, end),配合FormData附带分片序号、总片数、文件唯一标识(如 hash); - 后端接收后不合并,先存临时分片(如按
uploadId/chunk_001路径落盘); - 所有分片上传成功后,再由服务端合并(避免浏览器参与拼接);
- 推荐加 MD5 或 SparkMD5 计算文件级哈希,用于秒传和断点续传判断。
规避预览与渲染带来的额外内存压力
用户常误以为“只是传个文件”,但若同时做图片预览、PDF 首页渲染、音视频元信息读取等,内存会雪上加霜:
- 禁用自动预览高清图:不要用
readAsDataURL(Base64 膨胀 33%,且生成巨大字符串);改用URL.createObjectURL(file)创建临时 blob URL,仅用于或标签; - PDF 预览不用 pdf.js 全量加载:改用服务端转缩略图(第一页 PNG)或返回文本摘要;
- 上传过程中禁用其他 heavy 操作(如复杂 Canvas 绘图、大量 IndexedDB 写入)。
增强容错与降级能力
即使做了分片,极端弱网或低端设备仍可能卡住。需主动兜底:
- 每个分片上传设超时(如 30s),超时即重试(最多 3 次)或降级为普通表单提交(
); - 监听
window.onbeforeunload提示用户“上传未完成”,并缓存已传分片 ID 到 sessionStorage; - 检测到
QuotaExceededError或频繁 GC 滞缓时,自动切换为纯 input file 原生上传(放弃进度条和断点); - 移动端建议 fallback 到唤起系统相册/文件管理器(
capture="filesystem"已废弃,用accept+capture组合更稳妥)。










