Layui多文件上传失败后自动清除失败项,需手动维护pendingFiles数组和statusMap实现单文件重传;必须禁用unified: true、清空input值或调用resetFile(),并用原生请求替代obj.upload()。
重试时找不到原始文件对象,因为Layui自动清除了失败项
多文件上传中某个文件失败后,obj.upload() 再调用会跳过它——不是bug,是layui默认行为。组件在 done 或 error 回调触发后,会从内部 this.files 队列里删掉对应索引的 file 对象;后续重试时 obj.upload() 只遍历剩余文件,失败项已“消失”。
关键点在于:你不能依赖组件自己记状态,必须自己存。
- 在
choose回调里用Array.from(obj.files)转成数组,存到闭包变量(如pendingFiles = []),并为每个文件生成唯一id(比如Date.now() + index) - 维护一个
statusMap = { [id]: 'failed' },在error里更新,不删pendingFiles中的项 - 预览列表每行加一个
type="button"的「重传」按钮,绑定该文件id,点击时从pendingFiles找出对应File实例
重传必须绕过obj.upload(),改用原生请求
想复用 Layui 的配置(如 url、headers),但又得控制单个文件重发,就不能走组件封装的上传链路。否则要么全队列重来,要么根本拿不到失败文件的引用。
正确做法是手动构造请求:
- 提前缓存配置:
const uploadCfg = { url: '/upload', headers: { token: layui.data('user')?.token } } - 重传时用
FormData+fetch或XMLHttpRequest发送,把文件塞进FormData.append('file', file) - 如果后端支持校验,上传前先发一次
HEAD /check-exists?hash=xxx,存在则直接回填结果,避免重复存 - 禁用重传按钮(
btn.disabled = true),done或error后再恢复,防手抖连点
unified: true 模式下无法单文件重试
这个配置把所有选中的文件打包进一次请求,语义上就不存在“某个失败、其他成功”的情况。一旦失败,整个请求就断了,statusMap 里所有文件都会被标为 failed,重试只能整批再来。
如果你需要粒度可控的重试,必须关掉它:
- 显式设
unified: false(默认值),让 Layui 逐个发起请求 - 不要在
choose里动态改obj.config.data,它不会为每个文件刷新;要用before回调配合FormData注入文件级参数 - 注意:Layui 自带的
chunked: true不提供分片去重能力,断点续传需服务端配合实现分片索引查询接口
auto 模式下重试前必须清空 input value
用户点击「重传」按钮后,如果底层还是靠触发 <input type="file"> 的 change 事件来选文件,那同一文件第二次选中不会触发事件——浏览器认为没变化。
所以哪怕只是“模拟重选”,也要主动清空 input 值:
- 在
error或重传逻辑开始时,执行obj.config.elem.next()[0].value = ''(适用于auto: true场景) - 或更稳妥地调用
obj.resetFile(),这是 Layui 提供的官方重置方法,内部做了 DOM 替换 - 若用
type="button"触发重传,确保按钮不在<form>内,或加type="button"属性,否则表单会提交刷新,清空已有数据
真正麻烦的从来不是怎么发请求,而是状态同步:前端要记住哪些文件失败了、是否正在重传、后端是否已存在。漏掉任意一环,用户点十次重传,后端可能存十份相同文件。


















