|
@@ -19,10 +19,14 @@ import cn.com.qmth.examcloud.starters.face.verify.model.param.FaceParam;
|
|
|
import cn.com.qmth.examcloud.starters.face.verify.model.param.ImageBase64Parm;
|
|
|
import cn.com.qmth.examcloud.starters.face.verify.model.param.ImageParm;
|
|
|
import cn.com.qmth.examcloud.starters.face.verify.service.FaceVerifyService;
|
|
|
+import cn.com.qmth.examcloud.support.cache.CacheHelper;
|
|
|
+import cn.com.qmth.examcloud.support.cache.bean.OrgPropertyCacheBean;
|
|
|
import cn.com.qmth.examcloud.support.fss.FssFactory;
|
|
|
import cn.com.qmth.examcloud.support.fss.model.FssFileInfo;
|
|
|
import cn.com.qmth.examcloud.web.enums.HttpServletRequestAttribute;
|
|
|
import cn.com.qmth.examcloud.web.support.ServletUtil;
|
|
|
+
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
@@ -56,22 +60,45 @@ public class FaceServiceImpl implements FaceService {
|
|
|
|
|
|
// @Value("${examcloud.face.verify.facePlusSecret}")
|
|
|
// private String apiSecret;
|
|
|
+ private boolean overwritePhoto(Long rootOrgId) {
|
|
|
+ OrgPropertyCacheBean orgProperty = CacheHelper.getOrgProperty(rootOrgId, "OVERWRITE_PHOTO");
|
|
|
+
|
|
|
+ if (orgProperty == null) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (orgProperty.getHasValue()) {
|
|
|
+ return "true".equals(orgProperty.getValue());
|
|
|
+ } else {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
@Override
|
|
|
- public void processFace(Long rootOrgId, String identityNumber, String fileSuffix, File photoFile,
|
|
|
- String operator) {
|
|
|
+ public void processFace(Long rootOrgId, String identityNumber, String fileSuffix, File photoFile, String operator) {
|
|
|
+ processFace(rootOrgId, identityNumber, fileSuffix, photoFile, operator, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void processFace(Long rootOrgId, String identityNumber, String fileSuffix, File photoFile, String operator,
|
|
|
+ boolean ignoreCfg) {
|
|
|
|
|
|
GetStudentReq req = new GetStudentReq();
|
|
|
req.setIdentityNumber(identityNumber);
|
|
|
req.setRootOrgId(rootOrgId);
|
|
|
GetStudentResp resp = studentCloudService.getStudent(req);
|
|
|
StudentBean student = resp.getStudentInfo();
|
|
|
-
|
|
|
+ if (!ignoreCfg) {
|
|
|
+ if (StringUtils.isNotBlank(student.getPhotoPath()) && !overwritePhoto(rootOrgId)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
// 人脸识别验证
|
|
|
this.faceDetect(photoFile, identityNumber);
|
|
|
|
|
|
// 路径规则:/student_base_photo/{rootOrgId}/{userId}/{timeMillis}{fileSuffix}
|
|
|
- String filePath = String.format("/student_base_photo/%s/%s/%s%s", rootOrgId, student.getId(), System.currentTimeMillis(), fileSuffix);
|
|
|
+ String filePath = String.format("/student_base_photo/%s/%s/%s%s", rootOrgId, student.getId(),
|
|
|
+ System.currentTimeMillis(), fileSuffix);
|
|
|
FssFileInfo result = FssFactory.getInstance().writeFile(filePath, photoFile, null);
|
|
|
|
|
|
// String photoUrl = result.getFileUrl();
|
|
@@ -96,14 +123,15 @@ public class FaceServiceImpl implements FaceService {
|
|
|
request.setPhotoPath(filePath);
|
|
|
studentCloudService.updatePhotoPath(request);
|
|
|
|
|
|
- LOG.warn("更新学生底照完成!studentId:{} identityNumber:{} operator:{} photoUrl:{}",
|
|
|
- student.getId(), identityNumber, operator, result.getFileUrl());
|
|
|
+ LOG.warn("更新学生底照完成!studentId:{} identityNumber:{} operator:{} photoUrl:{}", student.getId(), identityNumber,
|
|
|
+ operator, result.getFileUrl());
|
|
|
|
|
|
- //操作日志
|
|
|
- User accessUser = (User) ServletUtil.getRequest().getAttribute(HttpServletRequestAttribute.$_ACCESS_USER.name());
|
|
|
+ // 操作日志
|
|
|
+ User accessUser = (User) ServletUtil.getRequest()
|
|
|
+ .getAttribute(HttpServletRequestAttribute.$_ACCESS_USER.name());
|
|
|
if (accessUser != null) {
|
|
|
- ReportsUtil.report(new OperateReport(rootOrgId, accessUser.getUserId(), student.getId(), null
|
|
|
- , UserType.COMMON, OperateContent.STUDENT_PHOTO_IMPORT.getDesc()));
|
|
|
+ ReportsUtil.report(new OperateReport(rootOrgId, accessUser.getUserId(), student.getId(), null,
|
|
|
+ UserType.COMMON, OperateContent.STUDENT_PHOTO_IMPORT.getDesc()));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -112,7 +140,8 @@ public class FaceServiceImpl implements FaceService {
|
|
|
|
|
|
try {
|
|
|
ImageParm basePhoto = new ImageBase64Parm(imageBase64);
|
|
|
- FaceResult result = faceVerifyService.faceDetect(FaceParam.builder().images(basePhoto).apiType(FaceApiType.PRIVATE_BAIDU_API));
|
|
|
+ FaceResult result = faceVerifyService
|
|
|
+ .faceDetect(FaceParam.builder().images(basePhoto).apiType(FaceApiType.PRIVATE_BAIDU_API));
|
|
|
|
|
|
if (result.isFacePass()) {
|
|
|
LOG.warn("人脸检测通过!identityNumber:{} photoPath:{}", identityNumber, photoFile.getAbsolutePath());
|
|
@@ -120,16 +149,19 @@ public class FaceServiceImpl implements FaceService {
|
|
|
}
|
|
|
|
|
|
if (result.isApiNeedRetry()) {
|
|
|
- LOG.warn("人脸检测接口异常!identityNumber:{} photoPath:{} err:{}", identityNumber, photoFile.getAbsolutePath(), result.getError());
|
|
|
+ LOG.warn("人脸检测接口异常!identityNumber:{} photoPath:{} err:{}", identityNumber, photoFile.getAbsolutePath(),
|
|
|
+ result.getError());
|
|
|
throw new StatusException("620008", "人脸检测接口异常,请稍后重试!");
|
|
|
}
|
|
|
|
|
|
- LOG.warn("人脸检测失败!identityNumber:{} photoPath:{} err:{}", identityNumber, photoFile.getAbsolutePath(), result.getError());
|
|
|
+ LOG.warn("人脸检测失败!identityNumber:{} photoPath:{} err:{}", identityNumber, photoFile.getAbsolutePath(),
|
|
|
+ result.getError());
|
|
|
|
|
|
basePhoto = null;
|
|
|
imageBase64 = null;
|
|
|
} catch (Exception e) {
|
|
|
- LOG.error("人脸检测错误!identityNumber:{} photoPath:{} err:{}", identityNumber, photoFile.getAbsolutePath(), e.getMessage());
|
|
|
+ LOG.error("人脸检测错误!identityNumber:{} photoPath:{} err:{}", identityNumber, photoFile.getAbsolutePath(),
|
|
|
+ e.getMessage());
|
|
|
}
|
|
|
|
|
|
throw new StatusException("620005", "人脸检测失败!");
|
|
@@ -140,148 +172,119 @@ public class FaceServiceImpl implements FaceService {
|
|
|
*
|
|
|
* @author WANGWEI
|
|
|
*/
|
|
|
- /*private Map<String, Object> addFaceToken2Faceset(Long rootOrgId, String faceToken) {
|
|
|
-
|
|
|
- Map<String, Object> info = Maps.newHashMap();
|
|
|
- info.put("rootOrgId", rootOrgId);
|
|
|
- info.put("faceToken", faceToken);
|
|
|
- int times = 0;
|
|
|
- while (true) {
|
|
|
- String facesetToken = getFacesetToken(rootOrgId);
|
|
|
- info.put("facesetToken", facesetToken);
|
|
|
-
|
|
|
- if (times >= 3) {
|
|
|
- LOG.error("添加faceToken至faceSet失败. info:{}", JsonUtil.toJson(info));
|
|
|
- throw new StatusException("620005", "人脸信息添加失败");
|
|
|
- }
|
|
|
-
|
|
|
- CloseableHttpClient httpClient = HttpClients.createDefault();
|
|
|
- CloseableHttpResponse httpResponse = null;
|
|
|
- try {
|
|
|
- URI uri = new URIBuilder().setScheme("https").setHost("api-cn.faceplusplus.com")
|
|
|
- .setPath("/facepp/v3/faceset/addface").setParameter("api_key", apiKey)
|
|
|
- .setParameter("api_secret", apiSecret)
|
|
|
- .setParameter("faceset_token", facesetToken)
|
|
|
- .setParameter("face_tokens", faceToken).build();
|
|
|
-
|
|
|
- LOG.info("[Face++ Rquest]. url=" + uri.toString());
|
|
|
-
|
|
|
- HttpPost httpPost = new HttpPost(uri);
|
|
|
-
|
|
|
- httpResponse = httpClient.execute(httpPost);
|
|
|
- HttpEntity entity = httpResponse.getEntity();
|
|
|
- int statusCode = httpResponse.getStatusLine().getStatusCode();
|
|
|
- String respBody = EntityUtils.toString(entity, "UTF-8");
|
|
|
-
|
|
|
- LOG.info("[Face++ Response]. statusCode=" + statusCode + "; respBody=" + respBody);
|
|
|
-
|
|
|
- if (respBody.contains("QUOTA_EXCEEDED")) {
|
|
|
- throw new StatusException("620006", "faceset is full");
|
|
|
- }
|
|
|
-
|
|
|
- if (statusCode == HttpStatus.SC_OK) {
|
|
|
- JSONObject jsonObject = JSON.parseObject(respBody);
|
|
|
- int faceAdded = jsonObject.getInteger("face_added");
|
|
|
- int faceCount = jsonObject.getInteger("face_count");
|
|
|
- if (1 == faceAdded) {
|
|
|
- Map<String, Object> ret = Maps.newHashMap();
|
|
|
- ret.put("facesetToken", facesetToken);
|
|
|
- ret.put("faceCount", (long) faceCount);
|
|
|
- return ret;
|
|
|
- }
|
|
|
- } else if (statusCode == HttpStatus.SC_FORBIDDEN) {
|
|
|
- if (respBody.contains("CONCURRENCY_LIMIT_EXCEEDED")) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- times++;
|
|
|
- } catch (Exception e) {
|
|
|
- times++;
|
|
|
- LOG.error("添加faceToken接口异常. info:{} errCount:{} err:{}", JsonUtil.toJson(info), times, e.getMessage());
|
|
|
- } finally {
|
|
|
- HttpClientUtil.close(httpResponse);
|
|
|
- }
|
|
|
- }
|
|
|
- }*/
|
|
|
+ /*
|
|
|
+ * private Map<String, Object> addFaceToken2Faceset(Long rootOrgId, String
|
|
|
+ * faceToken) {
|
|
|
+ *
|
|
|
+ * Map<String, Object> info = Maps.newHashMap(); info.put("rootOrgId",
|
|
|
+ * rootOrgId); info.put("faceToken", faceToken); int times = 0; while (true)
|
|
|
+ * { String facesetToken = getFacesetToken(rootOrgId);
|
|
|
+ * info.put("facesetToken", facesetToken);
|
|
|
+ *
|
|
|
+ * if (times >= 3) { LOG.error("添加faceToken至faceSet失败. info:{}",
|
|
|
+ * JsonUtil.toJson(info)); throw new StatusException("620005", "人脸信息添加失败");
|
|
|
+ * }
|
|
|
+ *
|
|
|
+ * CloseableHttpClient httpClient = HttpClients.createDefault();
|
|
|
+ * CloseableHttpResponse httpResponse = null; try { URI uri = new
|
|
|
+ * URIBuilder().setScheme("https").setHost("api-cn.faceplusplus.com")
|
|
|
+ * .setPath("/facepp/v3/faceset/addface").setParameter("api_key", apiKey)
|
|
|
+ * .setParameter("api_secret", apiSecret) .setParameter("faceset_token",
|
|
|
+ * facesetToken) .setParameter("face_tokens", faceToken).build();
|
|
|
+ *
|
|
|
+ * LOG.info("[Face++ Rquest]. url=" + uri.toString());
|
|
|
+ *
|
|
|
+ * HttpPost httpPost = new HttpPost(uri);
|
|
|
+ *
|
|
|
+ * httpResponse = httpClient.execute(httpPost); HttpEntity entity =
|
|
|
+ * httpResponse.getEntity(); int statusCode =
|
|
|
+ * httpResponse.getStatusLine().getStatusCode(); String respBody =
|
|
|
+ * EntityUtils.toString(entity, "UTF-8");
|
|
|
+ *
|
|
|
+ * LOG.info("[Face++ Response]. statusCode=" + statusCode + "; respBody=" +
|
|
|
+ * respBody);
|
|
|
+ *
|
|
|
+ * if (respBody.contains("QUOTA_EXCEEDED")) { throw new
|
|
|
+ * StatusException("620006", "faceset is full"); }
|
|
|
+ *
|
|
|
+ * if (statusCode == HttpStatus.SC_OK) { JSONObject jsonObject =
|
|
|
+ * JSON.parseObject(respBody); int faceAdded =
|
|
|
+ * jsonObject.getInteger("face_added"); int faceCount =
|
|
|
+ * jsonObject.getInteger("face_count"); if (1 == faceAdded) { Map<String,
|
|
|
+ * Object> ret = Maps.newHashMap(); ret.put("facesetToken", facesetToken);
|
|
|
+ * ret.put("faceCount", (long) faceCount); return ret; } } else if
|
|
|
+ * (statusCode == HttpStatus.SC_FORBIDDEN) { if
|
|
|
+ * (respBody.contains("CONCURRENCY_LIMIT_EXCEEDED")) { continue; } }
|
|
|
+ *
|
|
|
+ * times++; } catch (Exception e) { times++;
|
|
|
+ * LOG.error("添加faceToken接口异常. info:{} errCount:{} err:{}",
|
|
|
+ * JsonUtil.toJson(info), times, e.getMessage()); } finally {
|
|
|
+ * HttpClientUtil.close(httpResponse); } } }
|
|
|
+ */
|
|
|
|
|
|
/**
|
|
|
* 方法注释
|
|
|
*
|
|
|
* @author WANGWEI
|
|
|
*/
|
|
|
- /*private String getFacesetToken(Long rootOrgId) {
|
|
|
-
|
|
|
- GetUsableFacesetListReq req = new GetUsableFacesetListReq();
|
|
|
- req.setRootOrgId(rootOrgId);
|
|
|
- GetUsableFacesetListResp resp = faceCloudService.getUsableFacesetList(req);
|
|
|
- List<FacesetBean> facesetBeanList = resp.getFacesetBeanList();
|
|
|
-
|
|
|
- if (CollectionUtils.isEmpty(facesetBeanList)) {
|
|
|
- throw new StatusException("630001", "无可用的faceset");
|
|
|
- }
|
|
|
-
|
|
|
- FacesetBean facesetBean = facesetBeanList.get(0);
|
|
|
- return facesetBean.getFacesetToken();
|
|
|
- }*/
|
|
|
+ /*
|
|
|
+ * private String getFacesetToken(Long rootOrgId) {
|
|
|
+ *
|
|
|
+ * GetUsableFacesetListReq req = new GetUsableFacesetListReq();
|
|
|
+ * req.setRootOrgId(rootOrgId); GetUsableFacesetListResp resp =
|
|
|
+ * faceCloudService.getUsableFacesetList(req); List<FacesetBean>
|
|
|
+ * facesetBeanList = resp.getFacesetBeanList();
|
|
|
+ *
|
|
|
+ * if (CollectionUtils.isEmpty(facesetBeanList)) { throw new
|
|
|
+ * StatusException("630001", "无可用的faceset"); }
|
|
|
+ *
|
|
|
+ * FacesetBean facesetBean = facesetBeanList.get(0); return
|
|
|
+ * facesetBean.getFacesetToken(); }
|
|
|
+ */
|
|
|
|
|
|
/**
|
|
|
* 方法注释
|
|
|
*
|
|
|
* @author WANGWEI
|
|
|
*/
|
|
|
- /*private String detect(String photoUrl) {
|
|
|
- int times = 0;
|
|
|
- String faceToken = null;
|
|
|
- while (true) {
|
|
|
- if (times >= 3) {
|
|
|
- LOG.error("人脸检测失败. photoUrl:{}", photoUrl);
|
|
|
- throw new StatusException("620005", "人脸检测失败");
|
|
|
- }
|
|
|
-
|
|
|
- CloseableHttpClient httpClient = HttpClients.createDefault();
|
|
|
- CloseableHttpResponse httpResponse = null;
|
|
|
- try {
|
|
|
- URI uri = new URIBuilder().setScheme("https").setHost("api-cn.faceplusplus.com")
|
|
|
- .setPath("/facepp/v3/detect").setParameter("api_key", apiKey)
|
|
|
- .setParameter("api_secret", apiSecret).setParameter("image_url", photoUrl)
|
|
|
- .build();
|
|
|
-
|
|
|
- LOG.info("[Face++ Rquest]. url=" + uri.toString() + "; photoUrl=" + photoUrl);
|
|
|
-
|
|
|
- HttpPost httpPost = new HttpPost(uri);
|
|
|
-
|
|
|
- httpResponse = httpClient.execute(httpPost);
|
|
|
- HttpEntity entity = httpResponse.getEntity();
|
|
|
- int statusCode = httpResponse.getStatusLine().getStatusCode();
|
|
|
- String respBody = EntityUtils.toString(entity, "UTF-8");
|
|
|
-
|
|
|
- LOG.info("[Face++ Response]. statusCode=" + statusCode + "; respBody=" + respBody);
|
|
|
-
|
|
|
- if (statusCode == HttpStatus.SC_OK) {
|
|
|
- JSONObject jsonObject = JSON.parseObject(respBody);
|
|
|
- JSONArray faces = jsonObject.getJSONArray("faces");
|
|
|
- if (1 != faces.size()) {
|
|
|
- throw new StatusException("620009", "检测人脸数量不正确. photoUrl=" + photoUrl);
|
|
|
- }
|
|
|
-
|
|
|
- JSONObject face = faces.getJSONObject(0);
|
|
|
- faceToken = face.getString("face_token");
|
|
|
- return faceToken;
|
|
|
- } else if (statusCode == HttpStatus.SC_FORBIDDEN) {
|
|
|
- if (respBody.contains("CONCURRENCY_LIMIT_EXCEEDED")) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- times++;
|
|
|
- } catch (Exception e) {
|
|
|
- times++;
|
|
|
- LOG.error("人脸检测接口异常. photoUrl:{} errCount:{} err:{}", photoUrl, times, e.getMessage());
|
|
|
- } finally {
|
|
|
- HttpClientUtil.close(httpResponse);
|
|
|
- }
|
|
|
- }
|
|
|
- }*/
|
|
|
+ /*
|
|
|
+ * private String detect(String photoUrl) { int times = 0; String faceToken
|
|
|
+ * = null; while (true) { if (times >= 3) { LOG.error("人脸检测失败. photoUrl:{}",
|
|
|
+ * photoUrl); throw new StatusException("620005", "人脸检测失败"); }
|
|
|
+ *
|
|
|
+ * CloseableHttpClient httpClient = HttpClients.createDefault();
|
|
|
+ * CloseableHttpResponse httpResponse = null; try { URI uri = new
|
|
|
+ * URIBuilder().setScheme("https").setHost("api-cn.faceplusplus.com")
|
|
|
+ * .setPath("/facepp/v3/detect").setParameter("api_key", apiKey)
|
|
|
+ * .setParameter("api_secret", apiSecret).setParameter("image_url",
|
|
|
+ * photoUrl) .build();
|
|
|
+ *
|
|
|
+ * LOG.info("[Face++ Rquest]. url=" + uri.toString() + "; photoUrl=" +
|
|
|
+ * photoUrl);
|
|
|
+ *
|
|
|
+ * HttpPost httpPost = new HttpPost(uri);
|
|
|
+ *
|
|
|
+ * httpResponse = httpClient.execute(httpPost); HttpEntity entity =
|
|
|
+ * httpResponse.getEntity(); int statusCode =
|
|
|
+ * httpResponse.getStatusLine().getStatusCode(); String respBody =
|
|
|
+ * EntityUtils.toString(entity, "UTF-8");
|
|
|
+ *
|
|
|
+ * LOG.info("[Face++ Response]. statusCode=" + statusCode + "; respBody=" +
|
|
|
+ * respBody);
|
|
|
+ *
|
|
|
+ * if (statusCode == HttpStatus.SC_OK) { JSONObject jsonObject =
|
|
|
+ * JSON.parseObject(respBody); JSONArray faces =
|
|
|
+ * jsonObject.getJSONArray("faces"); if (1 != faces.size()) { throw new
|
|
|
+ * StatusException("620009", "检测人脸数量不正确. photoUrl=" + photoUrl); }
|
|
|
+ *
|
|
|
+ * JSONObject face = faces.getJSONObject(0); faceToken =
|
|
|
+ * face.getString("face_token"); return faceToken; } else if (statusCode ==
|
|
|
+ * HttpStatus.SC_FORBIDDEN) { if
|
|
|
+ * (respBody.contains("CONCURRENCY_LIMIT_EXCEEDED")) { continue; } }
|
|
|
+ *
|
|
|
+ * times++; } catch (Exception e) { times++;
|
|
|
+ * LOG.error("人脸检测接口异常. photoUrl:{} errCount:{} err:{}", photoUrl, times,
|
|
|
+ * e.getMessage()); } finally { HttpClientUtil.close(httpResponse); } } }
|
|
|
+ */
|
|
|
|
|
|
}
|