使用jQuery人脸检测验证上传护照照片时出现getImageData错误
解决人脸检测插件在FileReader预览后报错的问题
问题根源
报错的核心原因是图片还没加载完成就触发了人脸检测:通过FileReader给img标签设置src后,图片加载是异步过程,此时图片的宽高还没被浏览器解析(width为0),插件调用getImageData自然会失败。另外原代码在页面初始化时就给空图片绑定了检测,后续上传新图后也没重新触发检测,逻辑上存在漏洞。
修复方案
- 移除页面初始化时的
faceDetection绑定,改为在图片加载完成后再执行检测 - 给预览图片添加
load事件监听,确保图片完全加载后再调用人脸检测 - 每次上传新图时,先清除之前的人脸标记(优化体验)
修改后的完整代码
HTML
<!DOCTYPE html> <html> <head> <title>Face Detection - LaravelCode</title> <script src="../Content/Scripts/jquery-3.6.0.js"></script> <script src="../Content/Scripts/jquery.facedetection/jquery.facedetection.min.js"></script> </head> <body> <div class="container"> <div class="row"> <input type="file" id="fp" /> </div> <div class="row"> <img id="previewImg" src="" alt="img"> <br /> </div> </div> </body> </html>
CSS
.picture-container { position: relative; width: 600px; height: auto; margin: 20px auto; border: 10px solid #fff; box-shadow: 0 5px 5px #000; } .picture { display: block; width: 100%; height: auto; } .face { position: absolute; border: 2px solid #FFF; } .row { margin: 20px }
JavaScript
$(function () { $("#fp").change(function (e) { var ext = $('#fp').val().split('.').pop().toLowerCase(); if ($.inArray(ext, ['gif', 'png', 'jpg', 'jpeg']) == -1) { $("#fp").val(""); alert('invalid extension!'); return; } const file = this.files[0]; if (file) { let reader = new FileReader(); reader.onload = function (event) { $("#previewImg").attr("src", event.target.result); }; reader.readAsDataURL(file); } e.preventDefault(); }); // 监听预览图片加载完成事件,加载完成后执行人脸检测 $("#previewImg").on('load', function() { // 清除之前的人脸标记 $('.face').remove(); // 执行人脸检测 $(this).faceDetection({ complete: function (faces) { if (faces.length > 0) { alert("Valid"); } else { alert("Not Valid"); } for (var i = 0; i < faces.length; i++) { $('<div>', { 'class': 'face', 'css': { 'position': 'absolute', 'left': faces[i].x * faces[i].scaleX + 'px', 'top': faces[i].y * faces[i].scaleY + 'px', 'width': faces[i].width * faces[i].scaleX + 'px', 'height': faces[i].height * faces[i].scaleY + 'px' } }).insertAfter(this); } }, error: function (code, message) { alert('Error: ' + message); } }); }); });
关键修改点
- 把
faceDetection的调用移到了图片的load事件回调里,确保图片完全加载后再执行检测 - 添加了清除旧人脸标记的逻辑,避免多次上传后标记重叠
- 修复了文件验证后的
return逻辑,避免无效文件继续执行后续代码
内容的提问来源于stack exchange,提问作者PAVAN
相关产品推荐
相关产品推荐

