0


uniapp 实现人脸认证

前言

对于前端来说,需要后端提供一个人脸识别接口,前端传入图片,接口识别并返回结果,如此看来,其实前端只需实现图片传入即可,但是其实不然,在传入图片时,需要进行以下几点操作:

  1. 判断图片格式,市场上比较常见的是.jpg.jpeg.png
  2. 计算文件大小,一般要求不超过5MB
  3. 对图片进行base64加密

其实前2点具体要看接口要求,但是第3点,是实现人脸识别必备步骤,下文重点讲述一下移动端实现人脸识别的base64加密方法

问题

项目主要使用的技术栈是uniapp,uniapp的优点是上手快,基于vue开发,但缺点也很明显,多环境兼容导致兼容性较差,真机调试和运行较慢。比如h5端可以轻松实现base64加密,但是安卓环境完全不行,因为本地上传图片时,会返回一个blob流,但是uniapp的blob流是以http://localhost…(安卓环境无法识别localhost) 开始,导致无法进行base64加密

解决办法

经过多方实现后,借用html5+ api的多个结合方法(

plus.zip.compressImage

plus.io.resolveLocalFileSystemURL

plus.io.FileReader

)实现加密,主要代码如下:

//app压缩图片  用for循环 来处理图片压缩 的问题,原因是 plus.zip.compressImage 方法 是异步执行的,for循环很快, 同时手机可执行的压缩方法有限制:应该是3个吧。超出直接就不执行了。所以 原理就是 在图片压缩成功后 继续 回调 压缩函数。 以到达循环压缩图片的功能。app_img(num, rem){let that =this;let index = rem.tempFiles[num].path.lastIndexOf('.');//获取图片地址最后一个点的位置let img_type = rem.tempFiles[num].path.substring(index +1, rem.tempFiles[num].path.length);//截取图片类型如png jpglet img_yuanshi = rem.tempFiles[num].path.substring(0, index);//截取图片原始路径let d2 =newDate().getTime();//时间戳//压缩图片
  plus.zip.compressImage({src: rem.tempFiles[num].path,//你要压缩的图片地址dst: img_yuanshi + d2 +'.'+ img_type,//压缩之后的图片地址(注意压缩之后的路径最好和原生路径的位置一样,不然真机上报code-5)quality:70//[10-100]},function(e){//压缩之后路径转base64位的//通过URL参数获取目录对象或文件对象
      plus.io.resolveLocalFileSystemURL(e.target,function(entry){// 可通过entry对象操作test.html文件
        entry.file(function(file){//获取文件数据对象var fileReader =newplus.io.FileReader();// 文件系统中的读取文件对象,用于获取文件的内容//alert("getFile:" + JSON.stringify(file));
          fileReader.readAsDataURL(file);//以URL编码格式读取文件数据内容
          fileReader.onloadend=function(evt){//读取文件成功完成的回调函数
            that.base64Img = evt.target.result.split(',')[1];//拿到‘data:image/jpeg;base64,‘后面的
            console.log('that.base64Img', that.base64Img);// rem.tempFiles[num].Base64_Path = evt.target.result.split(',')[1];};});});// that.base64Img = that.base64Img.concat(rem.tempFiles[num]);// 【注意】在此人脸认证中,只会传一张图片,故不考虑多张图片情况//利用递归循环来实现多张图片压缩// if (num == rem.tempFiles.length - 1) {//     return;// } else {//     that.app_img(num + 1, rem);// }},function(error){
      console.log('Compress error!');
      console.log(JSON.stringify(error));
      uni.showToast({title:'编码失败'+ error
      });});},

详细实现思路

其实对于uniapp实现人脸识别功能来讲,大概要经过这么几个步骤

  1. onImage():打开手机相册上传图片,获取blob流(本地临时地址)
  2. #ifdef APP-PLUS/#ifndef APP-PLUS:判断系统环境,是h5还是安卓环境,然后在进行图片压缩和加密,具体实现代码如下:
//#ifdef APP-PLUS//图片压缩
that.app_img(0, res);//#endif// #ifndef APP-PLUS
that.blobTobase64(res.tempFilePaths[0]);// #endif
  1. app_img()/blobTobase64():对要识别的图片进行base64加密
  2. onSave()—>upImage():附件上传,并处理识别信息

具体代码

<!-- 人脸认证 --><template><view><view class="u-margin-30 text-center"><u-avatar size="600":src="imageSrc"></u-avatar></view><view class="u-margin-60"><u-button type="primary"class="u-margin-top-60" @click="onImage">{{!imageSrc ?'拍照':'重拍'}}</u-button><!--<u-button type="primary"class="u-margin-top-30">重拍</u-button>--><u-button type="primary"class="u-margin-top-50" @click="onSave">保存</u-button></view><u-toast ref="uToast"/></view></template><script>import{ registerOrUpdateFaceInfo, UpdateLaborPersonnel }from'@/api/mww/labor.js';import{ UploadByProject }from'@/api/sys/upload.js';import{ sysConfig }from'@/config/config.js';import storage from'store';import{ACCESS_TOKEN}from'@/store/mutation-types';exportdefault{name:'face-authentication',data(){return{imageSrc:'',lastData:{},base64Img:'',base64:''};},onLoad(option){this.lastData =JSON.parse(decodeURIComponent(option.lastData));
        console.log('前一个页面数据',this.lastData);
        uni.setNavigationBarTitle({title:this.lastData.CnName +'-人脸认证 '});},methods:{onSave(){if(!this.imageSrc){this.$refs.uToast.show({title:'请先拍照',type:'error'});}// 人脸上传,附件上传,劳务人员信息修改this.upImage();},// h5压缩图片的方式,url为图片流blobTobase64(url){
            console.log('进来了2', url);let imgFile = url;let _this =this;
            uni.request({url: url,method:'GET',responseType:'arraybuffer',success:res=>{let base64 = uni.arrayBufferToBase64(res.data);//把arraybuffer转成base64
                    _this.base64Img ='data:image/jpeg;base64,'+ base64;//不加上这串字符,在页面无法显示}});},//app压缩图片  用for循环 来处理图片压缩 的问题,原因是 plus.zip.compressImage 方法 是异步执行的,for循环很快, 同时手机可执行的压缩方法有限制:应该是3个吧。超出直接就不执行了。所以 原理就是 在图片压缩成功后 继续 回调 压缩函数。 以到达循环压缩图片的功能。app_img(num, rem){let that =this;let index = rem.tempFiles[num].path.lastIndexOf('.');//获取图片地址最后一个点的位置let img_type = rem.tempFiles[num].path.substring(index +1, rem.tempFiles[num].path.length);//截取图片类型如png jpglet img_yuanshi = rem.tempFiles[num].path.substring(0, index);//截取图片原始路径let d2 =newDate().getTime();//时间戳//压缩图片
            plus.zip.compressImage({src: rem.tempFiles[num].path,//你要压缩的图片地址dst: img_yuanshi + d2 +'.'+ img_type,//压缩之后的图片地址(注意压缩之后的路径最好和原生路径的位置一样,不然真机上报code-5)quality:70//[10-100]},function(e){//压缩之后路径转base64位的//通过URL参数获取目录对象或文件对象
                    plus.io.resolveLocalFileSystemURL(e.target,function(entry){// 可通过entry对象操作test.html文件
                        entry.file(function(file){//获取文件数据对象var fileReader =newplus.io.FileReader();// 文件系统中的读取文件对象,用于获取文件的内容//alert("getFile:" + JSON.stringify(file));
                            fileReader.readAsDataURL(file);//以URL编码格式读取文件数据内容
                            fileReader.onloadend=function(evt){//读取文件成功完成的回调函数
                                that.base64Img = evt.target.result.split(',')[1];//拿到‘data:image/jpeg;base64,‘后面的
                                console.log('that.base64Img', that.base64Img);// rem.tempFiles[num].Base64_Path = evt.target.result.split(',')[1];};});});// that.base64Img = that.base64Img.concat(rem.tempFiles[num]);// 【注意】在此人脸认证中,只会传一张图片,故不考虑多张图片情况//利用递归循环来实现多张图片压缩// if (num == rem.tempFiles.length - 1) {//     return;// } else {//     that.app_img(num + 1, rem);// }},function(error){
                    console.log('Compress error!');
                    console.log(JSON.stringify(error));
                    uni.showToast({title:'编码失败'+ error
                    });});},// 打开手机相机相册功能onImage(){const that =this;// 安卓系统无法默认打开前置摄像头,具体请看下面app-plus原因,
            uni.chooseImage({count:1,//默认9sizeType:['original','compressed'],//可以指定是原图还是压缩图,默认二者都有sourceType:['camera'],// 打开摄像头-'camera',从相册选择-'album'success:function(res){
                    console.log('文件结果', res);if(res.tempFilePaths.length >0){// Blob流地址
                        that.imageSrc = res.tempFilePaths[0];//#ifdef APP-PLUS//图片压缩
                        that.app_img(0, res);//#endif// #ifndef APP-PLUS
                        that.blobTobase64(res.tempFilePaths[0]);// #endif}else{
                        that.$refs.uToast.show({title:'无文件信息',type:'error'});}},fail:function(res){
                    console.log('失败了', res.errMsg);
                    that.$refs.uToast.show({title: res.errMsg,type:'error'});}});// #ifdef APP-PLUS// console.log('app环境了');// 指定要获取摄像头的索引值,1表示主摄像头,2表示辅摄像头。如果没有设置则使用系统默认主摄像头。// 平台支持【注意注意注意】// Android - 2.2+ (不支持) :// 暂不支持设置默认使用的摄像头,忽略此属性值。打开拍摄界面后可操作切换。// iOS - 4.3+ (支持)// var cmr = plus.camera.getCamera(1);// var res = cmr.supportedImageResolutions[0];// var fmt = cmr.supportedImageFormats[0];// console.log('Resolution: ' + res + ', Format: ' + fmt);// cmr.captureImage(//     function(path) {//         alert('Capture image success: ' + path);//     },//     function(error) {//         alert('Capture image failed: ' + error.message);//     },//     { resolution: res, format: fmt }// );// #endif},// 上传附件至[人脸认证]服务器upImage(){if(!this.base64Img){this.$refs.uToast.show({title:'无图片信息',type:'error'});return;}const params ={identityId:this.lastData.IdCard,//身份证号码imgInfo:this.base64Img,//头像采用base64编码userId:this.lastData.Id,//劳务人员IduserName:this.lastData.CnName //劳务姓名};
            uni.showLoading();registerOrUpdateFaceInfo(params).then(res=>{if(res.success){this.$refs.uToast.show({title:'认证成功',type:'success'});// 上传至附件服务器+修改劳务人员信息this.uploadFile();}else{this.$refs.uToast.show({title:'认证失败,'+ res.message,type:'error'});
                        uni.hideLoading();}}).catch(err=>{
                    uni.hideLoading();
                    uni.showModal({title:'提示',content: err
                    });});},// 上传附件至附件服务器uploadFile(){const obj ={project:this.lastData.OrgCode ||this.$store.getters.projectCode.value,module:'mww.personnelCertification',segment:this.lastData.OrgCode,businessID:this.lastData.Id,storageType:1};let str =`project=${obj.project}&module=${obj.module}&segment=${obj.segment}&businessID=${obj.businessID}&storageType=${obj.storageType}`;
            console.log('str', str);// const url = '';// console.log('url', url);// const formData = new FormData();// formData.append('file', this.imageSrc, '.png');// UploadByProject(str, formData).then(res => {//     if (res.success) {//         this.$refs.uToast.show({//             title: '上传成功',//             type: 'success'//         });//     } else {//         this.$refs.uToast.show({//             title: res.message,//             type: 'error'//         });//     }// });const token = uni.getStorageSync(ACCESS_TOKEN);const that =this;// 需要使用uniapp提供的api,因为that.imageSrc的blob流为地址头为localhost(本地临时文件)
            uni.uploadFile({url:`${sysConfig().fileServer}/UploadFile/UploadByProject?${str}`,filePath: that.imageSrc,formData:{...obj
                },header:{// 必须传token,不然会报[系统标识不能为空]authorization:`Bearer ${token}`},name:'file',success:res=>{
                    that.$refs.uToast.show({title:'上传成功',type:'success'});
                    that.lastData.CertificationUrl = res.data[0].virtualPath;
                    that.lastData.Certification =1;
                    that.updateLaborPersonnel();},fail:err=>{
                    console.log('上传失败了', err);
                    that.$refs.uToast.show({title:'上传失败,'+ err,type:'error'});
                    uni.hideLoading();}});},// 修改劳务人员信息updateLaborPersonnel(){UpdateLaborPersonnel(this.lastData).then(res=>{if(res.success){this.$refs.uToast.show({title:'修改成功',type:'success'});// uni.showToast({//     title: '成功了'// });setTimeout(()=>{
                            uni.navigateBack({delta:1});},800);}else{this.$refs.uToast.show({title:'修改失败,'+ res.message,type:'error'});}}).finally(()=>{
                    uni.hideLoading();});}}};</script><style scoped lang="less"></style>

本文转载自: https://blog.csdn.net/weixin_41886421/article/details/129328784
版权归原作者 边中之城 所有, 如有侵权,请联系我们删除。

“uniapp 实现人脸认证”的评论:

还没有评论