choose是唯一可靠时机,因其参数obj.files为原生FileList,含name、size等元信息;before中obj.files为空,done仅返回服务端响应,preview会触发大文件读取风险且file为副本。
choose 是 layui upload 组件中唯一能可靠监听“用户完成选择文件”这一动作的回调,它在点击文件选择对话框并确认后立即触发,且同步暴露原始 file 对象 —— 其他回调(before、done、progress)均无法拿到未上传前的文件元信息。
为什么必须用 choose,而不是 before 或 done
before 回调里 obj.files 已为空(Layui 2.9+ 行为),obj.pushFile() 返回的是内部队列 ID 映射,不是原始 File 列表;done 只返回服务器响应,此时文件早已发走,前端再无机会读取本地 name 或 size。只有 choose 的参数 obj 上挂载着标准 FileList,即 obj.files,它是浏览器原生解析出的、零延迟的文件元数据集合。
choose 回调里怎么安全读取文件名和大小
单文件场景下直接取 obj.files[0] 即可,多文件则遍历 obj.files:
-
obj.files[0].name是原始文件名(含扩展名),不受重命名影响 -
obj.files[0].size单位是字节,转 KB 要除以1024(不是1014),保留一位小数可用(file.size / 1024).toFixed(1) - 别写成
obj.file.size(属性不存在)或obj.elem.files[0].size(elem是 Layui 封装后的 DOM,原生input.files已被清空) - IE10+ 支持,IE9 及以下无
FileList,需降级提示
常见误用:把 preview 当作选择监听入口
preview 回调(Layui 2.8+ 新增)只对图片/文本等可预览类型生效,且内部调用 FileReader.readAsDataURL(),会完整读取文件内容 —— 对大文件(>100MB)极易卡死主线程、爆内存,甚至被浏览器中止。你只是想监听“选了什么”,完全不需要走这趟重读流程。更关键的是:preview 的回调参数 file 是副本,某些旧版 Layui 在失败 fallback 时可能丢失 name 或 size。要取名取大小,请绕过 preview,直读 obj.files[i].name 和 obj.files[i].size。
如何在 choose 里阻止非法文件上传
校验逻辑放这里最稳妥,比如限制大小或格式:
- 判断
obj.files[0].size > 5 * 1024 * 1024(5MB),超限就obj.reset()清空选择,并return阻断后续流程 - 检查扩展名:用
file.name.split('.').pop().toLowerCase()提取后缀,比对白名单数组 - 注意:不能靠
accept或exts参数做最终校验,它们仅控制文件选择对话框的过滤器,用户仍可通过“所有文件”绕过 - 校验失败后必须
obj.reset(),否则下次选择时队列残留旧文件
真正容易被忽略的是:哪怕文件超过 2GB,obj.files[0].name 和 obj.files[0].size 依然能立刻拿到 —— 这是浏览器在点击“打开”后就解析好的元信息,不依赖读文件内容。问题往往出在后续环节:比如 preview 卡死、服务端没配好 client_max_body_size,或者误以为 choose 里能拿到路径(实际所有现代浏览器都屏蔽了真实路径,只返回文件名)。
文章来自机圈观察员网,发布者:,转载请注明出处:https://www.jqgcy.com/xinjizixun/127238.html