preview回调仅支持image/*类型文件,因内部依赖URL.createObjectURL()并塞入<img>标签,非图片文件(如PDF、ZIP)无法渲染,导致空白或报错;应按文件类型匹配图标占位,统一DOM结构切换显示,并设auto:false确保占位图稳定展示。
preview 回调是 Layui 2.8+ 新增的,但它只对 image/* 类型触发,且内部依赖 URL.createObjectURL() —— 对 PDF、DOCX、ZIP 这类非图片文件,浏览器无法将其渲染为图像,<img src="blob:..."> 会加载失败,控制台报错但无视觉反馈。你看到的只是空白或默认占位符(甚至不显示),用户完全不知所措。
核心思路:不依赖预览,而是根据 file.type 或后缀名匹配内置图标,动态插入带语义的占位元素。比 base64 图标更轻量,兼容性更好。
choose 回调中取 obj.files[0](单图)或遍历 Array.from(obj.files)(多图)/^application/pdf$/.test(file.type)、/.zip$/i.test(file.name) 等,避免仅靠 type(上传时可能为空)layui-icon layui-icon-file-briefcase),按类型映射:pdf → icon-pdf、zip → icon-zip、docx → icon-file-word
<img> 里塞非图片 URL;改用 <div class="file-icon"><i class="..."></i><div class="file-name">xxx.pdf</div></div>
避免写两套模板。统一用容器包裹,内部根据文件类型切换内容:
<div class="file-preview-item"><div class="preview-thumb"><!-- 图片走 img --><img src=""style="display:none"><!-- 非图走图标 + 名称 --><div class="icon-placeholder" style="display:none"><i class="layui-icon"></i><div class="file-name"></div></div></div></div>
在 choose 回调里做判断:
img.style.display = 'block'; div.icon-placeholder.style.display = 'none'; img.src = URL.createObjectURL(file)
img.style.display = 'none'; div.icon-placeholder.style.display = 'block'; 再设置 i.className 和 file-name.textContent
URL.revokeObjectURL(oldSrc),否则旧 blob 地址残留,内存涨得快如果 auto: true(默认),选完文件立刻发请求,choose 里刚设好占位图,上传就已开始——用户还没看清图标,进度条就动了,体验割裂。更糟的是,上传失败时页面还挂着旧占位图,用户无法分辨是否操作成功。
正确做法是显式设 auto: false,把上传动作收归到按钮点击或校验通过后手动调用 obj.upload(),确保占位图稳定显示至少 300ms 以上再触发网络请求。
非图片文件没有「预览」概念,只有「可识别的类型提示」。重点不是让它看起来像图,而是让用户一眼知道“这是个 PDF”“这是个压缩包”,别让图标和文件名脱节,也别在没释放 blob 的情况下反复生成新地址。