choose回调是唯一可靠时机读取obj.files,因其为原生FileList,含name、size等元信息;before/done中不可用,preview仅用于预览且有性能风险。
choose 回调里直接读 obj.files 是唯一可靠时机
layui 的 upload 组件不把原始 file 对象暴露给 before 或 done 回调,只有 choose 回调的参数 obj 上挂载了标准的 filelist——即 obj.files。错过这个回调,就拿不到未上传前的真实 name 和 size。
常见错误是试图在 before 里取 obj.files[0].name,但此时 obj.files 已为空(2.9.x 后行为),或根本不存在该属性;也有人误用 obj.pushFile() 想“推”出文件,但它只返回队列 ID 映射,不是原始 File 列表。
-
obj.files是原生FileList,每个元素都是标准File实例,含name、size、type、lastModified - 多选时
obj.files.length > 1,遍历即可;单选通常只取obj.files[0] - IE 10+ 支持,IE9 及以下无
FileList,需降级处理(如禁用多选、提示浏览器版本)
obj.preview() 不适合取名取大小,只适合预览
obj.preview() 是为图片/文本等可预览内容设计的,它内部调用 FileReader.readAsDataURL(),会触发完整文件读取——对大文件(尤其 >100MB)极易卡死主线程、爆内存、甚至被浏览器中止。你只是想看个名字和大小,完全没必要走这趟。
更关键的是:obj.preview() 的回调参数 file 是传入的副本,某些旧版 Layui(如 2.8.x)在大文件场景下可能丢失 name 或 size 属性(因 FileReader 失败后 fallback 不完整)。
- 要取名取大小,请绕过
preview,直读obj.files[i].name和obj.files[i].size - 若必须用
preview(比如要做缩略图),请加 try/catch 并设超时,避免阻塞 - 注意:
obj.files[i].size单位是字节,转 KB 记得除以1024,不是1014(网上很多示例写错了)
大文件(>2GB)下 obj.files 仍有效,但要注意兼容性边界
即使文件超过 2GB,obj.files[0].name 和 obj.files[0].size 依然能立刻拿到——因为浏览器在用户点击“打开”后就已解析出这些元信息,不依赖实际读文件内容。这是最轻量、最稳定的方式。
真正出问题的是后续环节:比如调用 obj.preview()、或后端接收时没配好(如 Nginx 的 client_max_body_size、PHP 的 upload_max_filesize)。前端取名取大小这步本身无上限。
- Chrome/Firefox/Edge 最新版均支持读取 >4GB 文件的
name和size - Safari 对超大文件的
size返回0(已知限制),此时可 fallback 到obj.files[0].name+ 提示“大小暂不可读” - 不要依赖
obj.pushFile()返回值来取size,它返回的是内部队列映射对象,size字段不一定存在
多文件连续选择同一文件时 choose 不触发?那是浏览器机制,不是 Layui bug
如果用户两次点同一个文件(比如先选 a.pdf,再点一次 a.pdf),Chrome 和 Firefox 默认不会再次触发 input[type=file] 的 change 事件,Layui 的 choose 自然也不执行。这不是组件缺陷,是浏览器防止重复提交的保护逻辑。
解决办法只能由业务层干预:比如每次渲染 upload 前手动清空 elem 的 value,或用 obj.reset() 主动重置输入框(注意要在 choose 外部调用,比如绑定到按钮 click)。
- 不要在
choose内调用obj.reset(),否则刚选完就清空,取不到文件 - 清空
value后需重新绑定 upload 实例(或调用upload.render()重建) - 更稳妥的做法是 UI 上禁用“重复选择”,用状态标记已选文件名,避免用户误操作


















