应逐个检查Array.from(e.dataTransfer.files)中每个file的size:若file.size === 0直接过滤;若file.size === 68且无扩展名(如"untitled")也视为Safari伪文件并排除,因files.length > 0不能保证存在有效文件。

怎么判断拖拽文件的 file.size 是否为 0
拖拽进来的文件 file.size === 0 是最直接的“空文件”信号,但不能只看这个值就下结论——Safari 拖入文件夹时会生成一个伪 File 对象,size 固定为 68 字节,name 却没有扩展名(比如叫 "untitled"),它既不是真实文件,也无法读取内容。
实操建议:
- 必须逐个检查
Array.from(e.dataTransfer.files)中每个file的size - 若
file.size === 0,直接过滤掉;若file.size === 68且!file.name.includes('.') && file.name !== '',也视为无效(Safari 文件夹典型特征) - 别依赖
file.type判断是否为空——空文件的type可能是""或任意字符串,无意义
为什么 e.dataTransfer.files.length > 0 不能说明有有效文件
这个条件只告诉你“浏览器交给你一个非空列表”,但里面可能全是 Safari 的 68 字节伪文件、或 Windows 下被重命名过的零字节占位符。更糟的是:某些 Android WebView 根本不填充 files,哪怕用户真拖了文件进来。
实操建议:
- 永远用
Array.from(e.dataTransfer.files).filter(f => f.size > 0 && !isSafariFolderPlaceholder(f))做第一道过滤 -
isSafariFolderPlaceholder可简单实现为:f.size === 68 && !/\./.test(f.name) && f.name.trim() !== '' - 不要在
drop事件里才开始校验——dragenter阶段就该用e.dataTransfer.items快速扫一遍 kind 和 type,提前提示“不支持文件夹”
拖拽文件夹时 files 为空但 items 有内容怎么办
Chrome/Firefox 支持拖文件夹,此时 e.dataTransfer.files 是空的,但 e.dataTransfer.items 里会有 kind: "file" 的项,并附带 webkitGetAsEntry() 方法。这是唯一能递归读取子文件的入口。
实操建议:
- 先检查
e.dataTransfer.items.length > 0,再遍历items,对每个item调用item.webkitGetAsEntry?.() - 如果返回
entry且entry.isDirectory为true,说明拖的是文件夹,需用entry.createReader().readEntries()异步展开 - 注意:该 API 在 Safari 和部分 WebView 中不可用,降级策略是直接拒绝并提示“请勿拖入文件夹”
真正安全的“空文件”判定要分两层
第一层是元信息层面:有没有可读的、非伪的 File 对象;第二层是内容层面:哪怕 size > 0,也可能因权限、路径或临时存储问题导致 FileReader 读取失败(如 DOMException: Failed to execute 'readAsArrayBuffer' on 'FileReader')。
所以最终上传前必须:
- 确保
file.size > 0且非 Safari 伪文件 - 用
file.slice(0, 1).arrayBuffer()做轻量探测(小文件可行,大文件跳过) - 在
FileReader.onload中确认实际读到了字节,而非触发onerror
最容易被忽略的是:把“拖进来就能用”当成默认假设。其实从 dragenter 到 readAsArrayBuffer 成功,中间至少有 4 个环节可能断裂——每个都得单独设防,不能靠一个 if (files.length) 带过。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











