不能在 upload.done 里加滤镜,因为此时图片已上传完成,CSS 滤镜仅影响显示而非原始文件;黑白处理必须在本地读取后、上传前完成,通过 FileReader 读取并预览,再用 canvas 手动灰度处理生成新 Blob 上传。
为什么不能在 upload.done 里加滤镜
因为 upload.done 是上传成功后触发的,此时图片早已发到服务端,前端拿到的是返回的 url,再对 url 加 filter: grayscale(100%) 只是让显示变灰,原始文件没变——你上传的还是彩色图。黑白处理必须发生在「本地读取后、上传前」这个阶段。
如何用 FileReader + CSS filter 预览黑白效果
核心是拦截用户选中的文件,用 FileReader 读成 dataURL,注入 <img> 标签并手动加滤镜样式,让用户看到实时预览效果:
- 必须设
auto: false,否则选完就自动上传,没机会干预 - 在
choose回调里调用obj.preview(file, function(dataUrl){ ... }),不要自己 new FileReader(obj.preview已封装好) - 把
dataUrl赋给一个预览<img id="preview-img">,再执行$('#preview-img').css({'-webkit-filter': 'grayscale(100%)', 'filter': 'grayscale(100%)'}) - 注意:只写
filter在 Safari 旧版会失效,-webkit-filter必须同时存在
上传时如何确保后端收到的是黑白图
上面只是预览变灰,真正上传的仍是原图。要让后端收到黑白图,得把 canvas 处理后的 Blob 交给 upload:
- 用
canvas绘制原图 → 调用ctx.filter = 'grayscale(100%)'(仅 Chrome/Firefox 支持,不推荐) - 更可靠的做法:用
ctx.getImageData()手动转灰度(逐像素计算0.299*R + 0.587*G + 0.114*B),再putImageData - 生成新 Blob 后,用
obj.upload(index, new Blob([canvas.toBlobData], {type: 'image/jpeg'}))提交(注意:Layui 2.8+ 支持传 Blob) - 别忘了设
acceptMime: 'image/jpeg',否则后端可能拒收
容易被忽略的兼容性坑
filter: grayscale() 是纯显示层操作,不影响文件内容;而 canvas 灰度处理在 iOS Safari 上可能因 canvas 尺寸超限(> 4096px)导致 toDataURL 返回 null。实际项目中建议:
- 限制预览最大宽高(如
max-width: 1200px),避免 canvas 过大 - 灰度处理前先缩放图片,尤其处理证件照等大图时
- 不要依赖
ctx.filter,它未被 Safari 全面支持,手算灰度最稳 - 如果只要预览灰,不改上传内容,就只做 CSS 滤镜;如果业务强制要求上传黑白图,就必须走 canvas 处理 + Blob 替换


















