Layui upload模块不支持原生多图预览,需在choose回调中用FileReader逐个读取obj.files生成DataURL并插入<img>标签,注意过滤非图片、限制数量与大小、避免内存溢出及兼容性问题。
layui upload 模块不支持原生多图预览,得自己补逻辑
layui 的 upload 模块默认只触发上传,不处理文件读取和预览。所谓“多文件上传预览”,本质是:选中文件 → 用 filereader 逐个读取 → 把 data url 赋给 <img> 标签。layui 不做这事,你得手动接上。
常见错误现象:upload.render() 配了 multiple: true,但界面上只看到上传按钮,没任何缩略图;或者点了“选择文件”后,choose 回调里没拿到 obj.files(其实是有的,只是没人读)。
- 必须在
choose回调里遍历obj.files,不能等done—— 那时文件早发到服务器了 -
obj.files是FileList,不是数组,要用Array.from()或循环处理 - 每个
File对象有name、size、type,可用来过滤非图片(比如跳过.pdf) - 别在
choose里直接调obj.upload(),否则会立刻上传,失去预览时机
怎么把选中的多个图片转成预览图并插入页面
核心就是用 FileReader 同步读取每个文件的 DataURL,然后动态生成 <img> 插入容器。注意顺序和内存控制。
使用场景:用户点击“选择文件”,弹出系统对话框,选中 3 张 JPG,页面下方立即显示三张缩略图 + 删除按钮。
- 给预览区准备一个容器,比如
<div id="preview-box"></div> - 在
choose回调里清空旧预览:document.getElementById('preview-box').innerHTML = '' - 对每个
file实例化一个FileReader,调用readAsDataURL(file) -
reader.onload触发后,用reader.result创建<img>,加src和自定义data-index方便后续删除 - 别用
for...of直接遍历obj.files并在循环里 new FileReader —— 闭包容易导致所有图片都显示最后一个
// 示例片段(放在 choose 回调内)
Array.from(obj.files).forEach((file, i) => {
if (!/image\/\w+/.test(file.type)) return;
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
const img = document.createElement('img');
img.src = reader.result;
img.style.maxWidth = '120px';
img.setAttribute('data-index', i);
document.getElementById('preview-box').appendChild(img);
};
});
为什么上传前预览常卡顿或崩溃
大图(比如 5MB 的 PNG)被 readAsDataURL 转成 base64 后,字符串体积膨胀约 33%,内存占用翻倍。10 张就可能撑爆浏览器堆栈,尤其低配设备。
性能影响:Chrome 下读取单张 8MP 图片平均耗时 150–300ms;10 张连续读,UI 线程明显卡顿,滚动失帧。
- 限制最大预览数量,比如最多显示 6 张:
if (obj.files.length > 6) return layer.msg('最多预览 6 张') - 限制单图大小,比如超过 2MB 就跳过预览(仍可上传):
if (file.size > 2 * 1024 * 1024) continue - 不用
readAsDataURL,改用createObjectURL(file)—— 内存更省、速度更快,但需手动revokeObjectURL防泄漏 - 预览图尺寸不必原图,可在
onload后用 Canvas 压缩再生成 URL(进阶需求,非必须)
layui upload 与现代浏览器兼容性要注意什么
FileList 和 FileReader 在 IE10+、Edge、Chrome、Firefox 都支持,但 IE11 不支持 FileReader.prototype.readAsArrayBuffer(这里用不到),所以基础预览没问题。真正坑的是移动端 Safari。
兼容性影响:iOS 12.5.7 的 Safari 中,input[type=file] 多选功能不稳定,有时只返回第一个文件;Android Chrome 通常正常。
- 别依赖
obj.files.length做唯一判断,加一层obj.files && obj.files.length防空 - Safari 移动端不支持
multiple属性?其实支持,但部分机型 UI 只允许单选 —— 这是系统限制,前端无法绕过 - 用
input元素自身监听change事件作为 fallback,避免过度依赖 layui 的choose回调 - 如果项目要兼容 IE9,这条路走不通,得换 Flash 或服务端预览方案
事情说清了就结束。真正麻烦的不是代码怎么写,而是用户选了 20 张图、每张 8MB,还希望秒出预览——这时候得接受“预览”和“上传”本来就是两件事,该截断就得截断。

















