浏览器原生文件夹选择支持webkitdirectory(Chrome/Safari)和directory(Firefox)属性,但不校验文件内容,0字节文件会进入FileList;需在change事件中遍历过滤file.size === 0项,并清空input.value;后端必须二次校验,否则易被绕过。

用 webkitdirectory 或 directory 选文件夹,但别指望它自动过滤空文件
浏览器原生支持文件夹选择,靠的是 input[type="file"] 的 webkitdirectory(Chrome/Safari)或 directory(Firefox)属性。加了这两个属性,用户就能点选整个文件夹,event.target.files 会返回一个扁平化的 FileList,里面是所有子文件(不含子文件夹对象)。但它**完全不检查文件内容**,0 字节文件照单全收——比如一个刚新建、还没保存内容的 notes.txt,也会进列表。
change 事件里必须手动遍历并剔除 file.size === 0 的项
前端唯一能拦截的位置就是 change 事件。不能只看 files[0],得遍历全部,尤其启用了 multiple 和文件夹上传后,files.length 可能上百。
- 用
if (file.size === 0)判断,别用!file.size—— 某些老旧浏览器里file.size可能是undefined,会误判 - 发现空文件,立刻执行
e.target.value = ''清空 input 值,否则下次选同一文件夹不会再次触发change - 提示用户时带上文件名:
console.warn(`跳过空文件: ${file.name}`),方便调试 - 如果要保留非空文件继续上传,得把过滤后的文件转成数组:
const validFiles = Array.from(files).filter(f => f.size > 0)
后端才是拦住空文件的不可替代一环
前端清空 value 或 preventDefault() 全都可被绕过:curl 直传、DevTools 改 DOM、禁用 JS 后提交……0 字节文件照样进后端。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- Node.js(Multer):
req.file.buffer?.length === 0(内存模式)或fs.statSync(req.file.path).size === 0(磁盘模式) - Java Spring:
multipartFile.getSize() == 0L,注意别只用isEmpty(),它只判null或空文件名 - PHP:
filesize($_FILES['f']['tmp_name']) === 0,别漏掉is_uploaded_file()先校验临时文件有效性 - 必须返回明确错误响应,如 HTTP 400 + JSON
{"error": "empty_file", "filename": "xxx"},不能静默丢弃
文件夹上传时,空文件常来自这些地方
零字节不是偶然现象,而是真实业务中高频出现的“合法异常”:
立即学习“前端免费学习笔记(深入)”;
- 设计稿源文件(.sketch、.fig)导出占位符
- 某些 SDK 自动生成的空日志文件或配置模板
- 用户右键新建文本文件但没保存就直接拖进上传框
- 压缩包解压中途失败,残留 0 字节的 .dat 或 .tmp 文件
前端过滤只是友好提示,后端校验才是安全底线;漏掉后端这层,攻击者就能用 0 字节文件填满磁盘或刷接口。


















