西宁建设工程信息网站,最新国际军事新闻头条新闻,如何给网站添加关键词,海南专业网站运营托管前言
对于前端来说#xff0c;需要后端提供一个人脸识别接口#xff0c;前端传入图片#xff0c;接口识别并返回结果#xff0c;如此看来#xff0c;其实前端只需实现图片传入即可#xff0c;但是其实不然#xff0c;在传入图片时#xff0c;需要进行以下几点操作需要后端提供一个人脸识别接口前端传入图片接口识别并返回结果如此看来其实前端只需实现图片传入即可但是其实不然在传入图片时需要进行以下几点操作
判断图片格式市场上比较常见的是.jpg、.jpeg、.png计算文件大小一般要求不超过5MB对图片进行base64加密
其实前2点具体要看接口要求但是第3点是实现人脸识别必备步骤下文重点讲述一下移动端实现人脸识别的base64加密方法
问题
项目主要使用的技术栈是uniappuniapp的优点是上手快基于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 new Date().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 new plus.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实现人脸识别功能来讲大概要经过这么几个步骤
onImage()打开手机相册上传图片获取blob流本地临时地址#ifdef APP-PLUS/#ifndef APP-PLUS判断系统环境是h5还是安卓环境然后在进行图片压缩和加密具体实现代码如下
//#ifdef APP-PLUS
//图片压缩
that.app_img(0, res);
//#endif// #ifndef APP-PLUS
that.blobTobase64(res.tempFilePaths[0]);
// #endifapp_img()/blobTobase64()对要识别的图片进行base64加密onSave()—upImage()附件上传并处理识别信息
具体代码
!-- 人脸认证 --
templateviewview classu-margin-30 text-centeru-avatar size600 :srcimageSrc/u-avatar/viewview classu-margin-60u-button typeprimary classu-margin-top-60 clickonImage{{ !imageSrc ? 拍照 : 重拍 }}/u-button!-- u-button typeprimary classu-margin-top-30重拍/u-button --u-button typeprimary classu-margin-top-50 clickonSave保存/u-button/viewu-toast refuToast //view
/templatescript
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;
export default {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 new Date().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 new plus.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从相册选择-albumsuccess: 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-PLUSthat.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();});}}
};
/scriptstyle scoped langless/style