必须在choose回调中压缩并用obj.resetfile()替换文件,禁用auto:true;因layui仅在此阶段暴露原始file列表且支持重置,before阶段无法修改,auto:true时直接跳过所有变更,否则后端将收到未压缩原图。
必须在 choose 回调里压缩,且禁用 auto: true,否则压缩无效——这是唯一能确保后端收到压缩图的路径。
为什么 choose 是唯一可靠入口
Layui 的 upload 模块只在 choose 阶段暴露原始 File 列表,并允许调用 obj.resetFile(index, blob, filename) 替换文件;before 阶段无法重置,auto: true 下直接跳过你对文件的任何修改。
-
obj.pushFile()返回的是可遍历的 plain object(非数组),键是内部生成的 index,不是数字下标 -
obj.preview()可用于实时预览 base64,但不参与上传逻辑,仅辅助调试 - 若误在
before里尝试替换file或修改obj.files,上传时仍发原始大图
如何用 canvas 压缩并正确塞回上传队列
核心是把压缩后的 Blob 通过 obj.resetFile() 显式写入,不能靠赋值或 push —— Layui 不监听 files 对象变更。
- 务必检查
file.type是否为image/jpeg或image/png,否则canvas.toDataURL('image/jpeg', 0.7)可能返回空字符串 -
quality推荐设为0.7~0.85:低于0.6模糊明显,高于0.9体积下降不明显 - 原图宽高超
4096px时,部分安卓 WebView 会崩溃,建议先等比缩放到maxWidth: 2000 -
filename必须保留原扩展名(如"photo.jpg"),否则后端Content-Type可能识别错误
多图场景下必须用 Promise.all() 控制并发
choose 回调是同步执行的,但图片压缩是异步过程。如果在 for...in 循环里直接调用 obj.upload(index, file),会导致顺序错乱、部分文件丢失甚至重复上传。
- 先用
Object.keys(files)获取安全索引数组,再逐个压缩并收集Promise - 所有压缩完成后统一调用
Promise.all(promises).then(() => { /* 批量 obj.upload() */ }) - 任一压缩失败时,应 fallback 到
obj.upload(index, files[index])上传原图,避免中断流程 - 不要在压缩回调里立即调用
obj.upload(),那只是“触发上传”,但此时文件可能还没被resetFile替换成功
最易被忽略的是:Layui 的 upload 并不感知你对 File 对象做的任何内存级修改,它只认 resetFile 写入的那一份。哪怕你用 URL.createObjectURL() 生成了新 blob,不调用 resetFile,上传的仍是原始文件。











