应通过 Array.from(e.dataTransfer.files).filter(f => f.size > 0).reduce((s, f) => s + f.size, 0) 计算总大小,iOS 等环境需 setTimeout 重检 size === 0 项,并在 FormData 构造后、fetch 前完成校验。

不能只靠 webkitdirectory 属性或单个 file.size 判断——文件夹拖拽后,e.dataTransfer.files 会包含子文件(甚至嵌套目录中的文件),但它们的 size 在部分环境(尤其是 iPad Safari)可能为 0 或延迟就绪,必须做有效性过滤和异步等待。
drop 事件里怎么正确汇总文件夹所有文件的总大小
用户拖一个文件夹进来,浏览器实际把其中每个可读文件都塞进 e.dataTransfer.files,但它是个只读 FileList,不能直接 reduce。关键步骤是:
- 用
Array.from(e.dataTransfer.files)转成数组 - 先
filter(file => file.size > 0)剔除无效项(如空文件、目录占位符、iOS 上未就绪的条目) - 再
reduce((sum, f) => sum + f.size, 0)累加,别用map().reduce()多遍历一次 - 如果发现大量
size === 0,尤其在 iOS 上,需加setTimeout(() => { /* 再校验 */ }, 100)等待底层填充完成
为什么只检查第一个文件或单个文件 size 完全没用
文件夹上传场景下,用户可能拖入 100 个 2MB 的 PNG,总和 200MB;而你只校验 files[0].size,结果是 2MB → 通过。后端收到 multipart 请求时,Content-Length 可能远超 client_max_body_size(Nginx 默认 1MB),直接返回 413,前端 fetch 却只报“网络失败”,查不出原因。
- 前端总大小限制值应比后端
client_max_body_size小 5–10%,留出 boundary 和字段开销 - 服务端也必须同步累计:Express + multer 不能只靠
limits.fileSize,得在fileFilter里维护已接收字节数;PHP 可读$_SERVER['CONTENT_LENGTH'],但要在请求体解析前拦截
移动端(尤其 iPad Safari)根本没真正“拖拽文件夹”
iPad Safari 不支持桌面级 dragover/drop 文件夹 API。所谓“拖拽上传”,本质是点击触发 ,然后从文件 App 选中整个文件夹——此时事件源是 change,不是 drop。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 别在
drop里写总大小逻辑,它在 iOS 上压根不触发 - 必须复用同一套校验函数,在
input[type="file"][webkitdirectory]的change事件里也执行完全相同的Array.from(files).filter(...).reduce(...) - 对
change事件,同样要处理size === 0的延迟问题,加setTimeout是必要手段
FormData 构造前必须完成总大小校验
你 append 的是 File 对象引用,不是二进制内容,所以校验必须发生在 new FormData() 之后、fetch() 之前。一旦进入上传流程,再想拦截就晚了。
- 校验失败立刻
return,清空 UI 状态(比如重置input.value = ''),避免用户看到“上传中”却卡死 - 不要在
for循环里逐个append再算总和——append不改变File对象本身,校验和构造应分离 - 若用分片上传,总大小校验仍需前置,只是后续按块发送;否则第一块发出去才发现超限,体验更差
最常被忽略的一点:文件夹上传时,webkitdirectory 的兼容性极差,Chrome/Edge 支持,Safari(包括 macOS)仅部分版本支持,iOS Safari 完全不认 drag-and-drop 文件夹语义——所以真正的降级路径不是“提示不支持”,而是统一走 change + webkitdirectory + 异步 size 等待,这才是能落地的方案。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










