|
@@ -1,15 +1,10 @@
|
|
package cn.com.qmth.examcloud.exchange.outer.service;
|
|
package cn.com.qmth.examcloud.exchange.outer.service;
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.BufferedReader;
|
|
-import java.io.IOException;
|
|
|
|
|
|
+import java.io.File;
|
|
import java.io.InputStreamReader;
|
|
import java.io.InputStreamReader;
|
|
import java.net.URI;
|
|
import java.net.URI;
|
|
-import java.net.URISyntaxException;
|
|
|
|
-import java.security.NoSuchAlgorithmException;
|
|
|
|
-import java.util.Date;
|
|
|
|
-import java.util.List;
|
|
|
|
|
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
|
import org.apache.http.HttpEntity;
|
|
import org.apache.http.HttpEntity;
|
|
import org.apache.http.StatusLine;
|
|
import org.apache.http.StatusLine;
|
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
|
@@ -22,22 +17,20 @@ import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
-import org.springframework.http.ResponseEntity;
|
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import com.google.gson.Gson;
|
|
import com.google.gson.Gson;
|
|
import com.google.gson.GsonBuilder;
|
|
import com.google.gson.GsonBuilder;
|
|
|
|
|
|
-import cn.com.qmth.examcloud.common.dto.core.Student;
|
|
|
|
-import cn.com.qmth.examcloud.common.dto.core.StudentFaceInfo;
|
|
|
|
-import cn.com.qmth.examcloud.common.dto.em.ExamStudent;
|
|
|
|
-import cn.com.qmth.examcloud.commons.base.util.GsonUtil;
|
|
|
|
|
|
+import cn.com.qmth.examcloud.commons.base.exception.StatusException;
|
|
|
|
+import cn.com.qmth.examcloud.commons.base.util.HttpClientUtil;
|
|
import cn.com.qmth.examcloud.commons.web.security.bean.User;
|
|
import cn.com.qmth.examcloud.commons.web.security.bean.User;
|
|
-import cn.com.qmth.examcloud.exchange.base.exception.DetectNoFaceException;
|
|
|
|
-import cn.com.qmth.examcloud.exchange.base.exception.ExamStudentNotExistException;
|
|
|
|
-import cn.com.qmth.examcloud.exchange.base.exception.FaceppException;
|
|
|
|
-import cn.com.qmth.examcloud.exchange.base.exception.InvalidJpgException;
|
|
|
|
-import cn.com.qmth.examcloud.exchange.base.exception.UpYunException;
|
|
|
|
|
|
+import cn.com.qmth.examcloud.core.basic.api.StudentCloudService;
|
|
|
|
+import cn.com.qmth.examcloud.core.basic.api.StudentFaceCloudService;
|
|
|
|
+import cn.com.qmth.examcloud.core.basic.api.bean.StudentBean;
|
|
|
|
+import cn.com.qmth.examcloud.core.basic.api.request.GetStudentReq;
|
|
|
|
+import cn.com.qmth.examcloud.core.basic.api.request.SaveStudentFaceInfoReq;
|
|
|
|
+import cn.com.qmth.examcloud.core.basic.api.response.GetStudentResp;
|
|
import cn.com.qmth.examcloud.exchange.dao.bean.FaceDetectResponse;
|
|
import cn.com.qmth.examcloud.exchange.dao.bean.FaceDetectResponse;
|
|
import cn.com.qmth.examcloud.exchange.outer.service.client.ExamStudentClient;
|
|
import cn.com.qmth.examcloud.exchange.outer.service.client.ExamStudentClient;
|
|
import cn.com.qmth.examcloud.exchange.outer.service.client.StudentFaceInfoClient;
|
|
import cn.com.qmth.examcloud.exchange.outer.service.client.StudentFaceInfoClient;
|
|
@@ -65,41 +58,38 @@ public class FaceppService {
|
|
@Autowired
|
|
@Autowired
|
|
StudentFaceInfoClient studentFaceInfoClient;
|
|
StudentFaceInfoClient studentFaceInfoClient;
|
|
|
|
|
|
- private void closeResponse(CloseableHttpResponse httpResponse) {
|
|
|
|
- if (httpResponse != null) {
|
|
|
|
- try {
|
|
|
|
- httpResponse.close();
|
|
|
|
- } catch (IOException e) {
|
|
|
|
- e.printStackTrace();
|
|
|
|
- } finally {
|
|
|
|
- httpResponse = null;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ @Autowired
|
|
|
|
+ StudentCloudService studentCloudService;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ StudentFaceCloudService studentFaceCloudService;
|
|
|
|
|
|
/**
|
|
/**
|
|
- * 检测人脸
|
|
|
|
|
|
+ * 重构<br>
|
|
|
|
+ * 调用人脸识别接口
|
|
*
|
|
*
|
|
|
|
+ * @author WANGWEI
|
|
* @param imageUrl
|
|
* @param imageUrl
|
|
- * @return 检测到的人脸的face_token
|
|
|
|
- * @throws URISyntaxException
|
|
|
|
- * @throws DetectNoFaceException
|
|
|
|
|
|
+ * @return
|
|
*/
|
|
*/
|
|
- public String detectSingleFace(String imageUrl)
|
|
|
|
- throws URISyntaxException, DetectNoFaceException {
|
|
|
|
- int time = 3;// 重新检测次数为3次
|
|
|
|
- String faceToken = "";
|
|
|
|
- while (time > 0) {
|
|
|
|
- // 调用人脸识别接口
|
|
|
|
- CloseableHttpClient httpClient = HttpClients.createDefault();
|
|
|
|
- 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", imageUrl)
|
|
|
|
- .build();
|
|
|
|
|
|
+ public String detectSingleFace(String imageUrl) {
|
|
|
|
+ // 重新检测次数为3次
|
|
|
|
+ int time = 3;
|
|
|
|
+ String faceToken = null;
|
|
|
|
+ while (true) {
|
|
|
|
+ if (time < 1) {
|
|
|
|
+ throw new StatusException("EX--111010", "人脸检测失败");
|
|
|
|
+ }
|
|
|
|
|
|
- HttpPost httpPost = new HttpPost(uri);
|
|
|
|
|
|
+ CloseableHttpClient httpClient = HttpClients.createDefault();
|
|
CloseableHttpResponse httpResponse = null;
|
|
CloseableHttpResponse httpResponse = null;
|
|
try {
|
|
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", imageUrl)
|
|
|
|
+ .build();
|
|
|
|
+ HttpPost httpPost = new HttpPost(uri);
|
|
|
|
+
|
|
httpResponse = httpClient.execute(httpPost);
|
|
httpResponse = httpClient.execute(httpPost);
|
|
HttpEntity responseEntity = httpResponse.getEntity();
|
|
HttpEntity responseEntity = httpResponse.getEntity();
|
|
int statusCode = httpResponse.getStatusLine().getStatusCode();
|
|
int statusCode = httpResponse.getStatusLine().getStatusCode();
|
|
@@ -114,186 +104,114 @@ public class FaceppService {
|
|
faceToken = faceDetectResponse.getFaces().get(0).getFace_token();
|
|
faceToken = faceDetectResponse.getFaces().get(0).getFace_token();
|
|
break;
|
|
break;
|
|
} else {
|
|
} else {
|
|
- throw new DetectNoFaceException();
|
|
|
|
|
|
+ time--;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
StringBuffer buffer = new StringBuffer();
|
|
StringBuffer buffer = new StringBuffer();
|
|
- String str = "";
|
|
|
|
- while (StringUtils.isNoneBlank((str = reader.readLine()))) {
|
|
|
|
|
|
+ String str = null;
|
|
|
|
+ while (null != (str = reader.readLine())) {
|
|
buffer.append(str);
|
|
buffer.append(str);
|
|
}
|
|
}
|
|
String result = buffer.toString();
|
|
String result = buffer.toString();
|
|
- LOG.info("获取token失败:" + result);
|
|
|
|
|
|
+ LOG.error("获取token失败:" + result);
|
|
time--;
|
|
time--;
|
|
}
|
|
}
|
|
httpClient.close();
|
|
httpClient.close();
|
|
- } catch (IOException e) {
|
|
|
|
- // 重试
|
|
|
|
- LOG.error("检测人脸失败,剩余次数:" + (time - 1), e);
|
|
|
|
|
|
+ } catch (Exception e) {
|
|
time--;
|
|
time--;
|
|
- if (time < 1) {
|
|
|
|
- throw new DetectNoFaceException();
|
|
|
|
- }
|
|
|
|
|
|
+ LOG.error("人脸检测失败", e);
|
|
} finally {
|
|
} finally {
|
|
- closeResponse(httpResponse);
|
|
|
|
|
|
+ HttpClientUtil.close(httpResponse);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- LOG.info("检测到人脸token:" + faceToken);
|
|
|
|
|
|
+
|
|
return faceToken;
|
|
return faceToken;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * 将人脸加入到人脸集合
|
|
|
|
|
|
+ * 添加faceToken至faceSet
|
|
*
|
|
*
|
|
|
|
+ * @author WANGWEI
|
|
* @param faceToken
|
|
* @param faceToken
|
|
* @param facesetToken
|
|
* @param facesetToken
|
|
- * @throws URISyntaxException
|
|
|
|
*/
|
|
*/
|
|
- public boolean addFace(String faceToken, String facesetToken) throws URISyntaxException {
|
|
|
|
- boolean success = false;
|
|
|
|
- int time = 3;// 重新检测次数为3次
|
|
|
|
|
|
+ public void addFaceToken2FaceTokenSet(String faceToken, String facesetToken) {
|
|
|
|
+
|
|
|
|
+ // 重新检测次数为3次
|
|
|
|
+ int time = 3;
|
|
while (time > 0) {
|
|
while (time > 0) {
|
|
// 调用人脸识别接口
|
|
// 调用人脸识别接口
|
|
CloseableHttpClient httpClient = HttpClients.createDefault();
|
|
CloseableHttpClient httpClient = HttpClients.createDefault();
|
|
- 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();
|
|
|
|
-
|
|
|
|
- HttpPost httpPost = new HttpPost(uri);
|
|
|
|
CloseableHttpResponse httpResponse = null;
|
|
CloseableHttpResponse httpResponse = null;
|
|
try {
|
|
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();
|
|
|
|
+
|
|
|
|
+ HttpPost httpPost = new HttpPost(uri);
|
|
httpResponse = httpClient.execute(httpPost);
|
|
httpResponse = httpClient.execute(httpPost);
|
|
StatusLine statusLine = httpResponse.getStatusLine();
|
|
StatusLine statusLine = httpResponse.getStatusLine();
|
|
- // 不能这么打印,会导致流关闭,从而造成异常。除非下面到代码不需要从流读取响应内容,则这里可以打印
|
|
|
|
- LOG.info("添加人脸到集合响应:" + EntityUtils.toString(httpResponse.getEntity()));
|
|
|
|
|
|
+ LOG.info("response: " + EntityUtils.toString(httpResponse.getEntity()));
|
|
if (statusLine.getStatusCode() == 200) {
|
|
if (statusLine.getStatusCode() == 200) {
|
|
- success = true;
|
|
|
|
- // 加入成功
|
|
|
|
break;
|
|
break;
|
|
} else {
|
|
} else {
|
|
time--;
|
|
time--;
|
|
}
|
|
}
|
|
- } catch (IOException e) {
|
|
|
|
- LOG.error("添加人脸失败,剩余次数:" + (time - 1), e);
|
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ LOG.error("添加faceToken至faceSet失败", e);
|
|
time--;
|
|
time--;
|
|
} finally {
|
|
} finally {
|
|
- closeResponse(httpResponse);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return success;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public void processOne(User accessUser, String fileName, byte[] dataBytes, Long rootOrgId)
|
|
|
|
- throws InvalidJpgException, ExamStudentNotExistException, NoSuchAlgorithmException,
|
|
|
|
- DetectNoFaceException, URISyntaxException, FaceppException, UpYunException {
|
|
|
|
- String userToken = accessUser.getUserToken();
|
|
|
|
- String[] nameAndSuffix = fileName.split("\\.");
|
|
|
|
- if (nameAndSuffix.length < 2) {
|
|
|
|
- throw new InvalidJpgException(fileName + "不是一个照片文件");
|
|
|
|
- }
|
|
|
|
- String identityNumber = (nameAndSuffix[0].startsWith("/")
|
|
|
|
- || nameAndSuffix[0].startsWith("\\"))
|
|
|
|
- ? nameAndSuffix[0].substring(1)
|
|
|
|
- : nameAndSuffix[0];
|
|
|
|
- String suffix = nameAndSuffix[1];
|
|
|
|
- LOG.info("文件名为 :" + identityNumber + ",后缀名为:" + suffix);
|
|
|
|
- // 根据身份证号码,查询考生是否存在
|
|
|
|
- LOG.info("查询身份证号码为 :" + identityNumber + "的学生");
|
|
|
|
- String json = examStudentClient.getExamStudentByIdentityNumber(userToken, identityNumber);
|
|
|
|
- // LOG.info("查询结果为 :" + json);
|
|
|
|
- if (StringUtils.isEmpty(json)) {
|
|
|
|
- LOG.error("身份证号为:" + identityNumber + "的考生不存在");
|
|
|
|
- throw new ExamStudentNotExistException();
|
|
|
|
- } else {
|
|
|
|
- List<ExamStudent> examStudentList = GsonUtil.jsonToArrayList(json, ExamStudent.class);
|
|
|
|
-
|
|
|
|
- if (examStudentList.size() < 1) {
|
|
|
|
- LOG.error("身份证号为:" + identityNumber + "的考生不存在");
|
|
|
|
- throw new ExamStudentNotExistException();
|
|
|
|
- }
|
|
|
|
- ExamStudent examStudent = examStudentList.get(0);
|
|
|
|
- // 保存学生照片到又拍云
|
|
|
|
- String upyunFileName = upyunService.getMd5(dataBytes);
|
|
|
|
- try {
|
|
|
|
- if (upyunService.saveStudentPhoto(identityNumber, dataBytes, upyunFileName,
|
|
|
|
- "." + suffix)) {
|
|
|
|
- // 调用人脸识别接口
|
|
|
|
- String faceToken = detectSingleFace(upyunService.getDownloadUrl(identityNumber,
|
|
|
|
- upyunFileName, "." + suffix));
|
|
|
|
- if (StringUtils.isBlank(faceToken)) {
|
|
|
|
- throw new FaceppException(identityNumber + "获取token失败");
|
|
|
|
- }
|
|
|
|
- String facesetToken = studentFaceInfoClient.getFaceSet(userToken);
|
|
|
|
- StudentFaceInfo studentFaceInfo = getStudentFaceInfo(userToken, identityNumber,
|
|
|
|
- rootOrgId);
|
|
|
|
- if (addFace(faceToken, facesetToken)) {
|
|
|
|
- String photoMD5 = upyunFileName + "." + suffix;
|
|
|
|
- saveStudentFaceInfo(studentFaceInfo, photoMD5, faceToken, facesetToken,
|
|
|
|
- examStudent.getStudentId(), accessUser.getDisplayName(),
|
|
|
|
- "INTERFACE_ADD", userToken);
|
|
|
|
- } else {
|
|
|
|
- throw new FaceppException(identityNumber + "保存当前faceToken到人脸集合(faceSet)失败");
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- throw new UpYunException("身份证号为:" + identityNumber + "的考生照片保存到又拍云失败");
|
|
|
|
- }
|
|
|
|
- } catch (IOException e) {
|
|
|
|
- throw new RuntimeException("身份证号为:" + identityNumber + "的考生照片保存失败", e);
|
|
|
|
|
|
+ HttpClientUtil.close(httpResponse);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * 方法注释
|
|
|
|
|
|
+ * 重构
|
|
*
|
|
*
|
|
* @author WANGWEI
|
|
* @author WANGWEI
|
|
- * @param userToken
|
|
|
|
- * @param identityNumber
|
|
|
|
- * @param rootOrgId
|
|
|
|
- * @return
|
|
|
|
|
|
+ * @param accessUser
|
|
|
|
+ * @param fileName
|
|
|
|
+ * @param file
|
|
|
|
+ * @throws Exception
|
|
*/
|
|
*/
|
|
- private StudentFaceInfo getStudentFaceInfo(String userToken, String identityNumber,
|
|
|
|
- Long rootOrgId) {
|
|
|
|
- ResponseEntity<StudentFaceInfo> respEntity = studentFaceInfoClient
|
|
|
|
- .getByIdentityNumber(userToken, identityNumber, rootOrgId);
|
|
|
|
|
|
+ public void uploadPhoto(User accessUser, String fileName, File file) throws Exception {
|
|
|
|
+ Long rootOrgId = accessUser.getRootOrgId();
|
|
|
|
+ String userToken = accessUser.getUserToken();
|
|
|
|
+ if (!(fileName.endsWith(".jpg") || fileName.endsWith(".png"))) {
|
|
|
|
+ throw new StatusException("B-101001", "文件格式错误");
|
|
|
|
+ }
|
|
|
|
|
|
- StudentFaceInfo studentFaceInfo = respEntity.getBody();
|
|
|
|
|
|
+ String identityNumber = fileName.substring(0, fileName.lastIndexOf(fileName));
|
|
|
|
|
|
- return studentFaceInfo;
|
|
|
|
- }
|
|
|
|
|
|
+ GetStudentReq req = new GetStudentReq();
|
|
|
|
+ req.setIdentityNumber(identityNumber);
|
|
|
|
+ req.setRootOrgId(accessUser.getRootOrgId());
|
|
|
|
+ GetStudentResp resp = studentCloudService.getStudent(req);
|
|
|
|
+ StudentBean student = resp.getStudentInfo();
|
|
|
|
|
|
- /**
|
|
|
|
- * 保存studentFaceInfo
|
|
|
|
- *
|
|
|
|
- * @param studentFaceInfo
|
|
|
|
- * @param photoMD5
|
|
|
|
- * @param faceToken
|
|
|
|
- * @param facesetToken
|
|
|
|
- * @param studentId
|
|
|
|
- * @param accessUserName
|
|
|
|
- * @param createType
|
|
|
|
- * @param userToken
|
|
|
|
- */
|
|
|
|
- public void saveStudentFaceInfo(StudentFaceInfo studentFaceInfo, String photoMD5,
|
|
|
|
- String faceToken, String facesetToken, Long studentId, String accessUserName,
|
|
|
|
- String createType, String userToken) {
|
|
|
|
- if (studentFaceInfo == null) {
|
|
|
|
- studentFaceInfo = new StudentFaceInfo();
|
|
|
|
- Student student = new Student();
|
|
|
|
- student.setId(studentId);
|
|
|
|
- studentFaceInfo.setStudent(student);
|
|
|
|
- studentFaceInfo.setCreateUser(accessUserName);
|
|
|
|
- studentFaceInfo.setCreateTime(new Date());
|
|
|
|
- } else {
|
|
|
|
- studentFaceInfo.setUpdateUser(accessUserName);
|
|
|
|
- studentFaceInfo.setUpdateTime(new Date());
|
|
|
|
- }
|
|
|
|
- studentFaceInfo.setFaceToken(faceToken);
|
|
|
|
- studentFaceInfo.setFaceSetToken(facesetToken);
|
|
|
|
- studentFaceInfo.setPhotoMD5(photoMD5);
|
|
|
|
- studentFaceInfo.setCreateType(createType);
|
|
|
|
- studentFaceInfoClient.save(userToken, studentFaceInfo);
|
|
|
|
|
|
+ String fileSuffix = fileName.substring(fileName.lastIndexOf("."));
|
|
|
|
+ String newFileName = System.currentTimeMillis() + fileSuffix;
|
|
|
|
+ String photoPath = upyunService.saveStudentPhoto(identityNumber, rootOrgId, newFileName,
|
|
|
|
+ file);
|
|
|
|
+
|
|
|
|
+ String url = upyunService.getStudentPhotoUrl(identityNumber, rootOrgId, newFileName);
|
|
|
|
+ // 调用人脸识别接口
|
|
|
|
+ String faceToken = detectSingleFace(url);
|
|
|
|
+
|
|
|
|
+ String facesetToken = studentFaceInfoClient.getFaceSet(userToken);
|
|
|
|
+
|
|
|
|
+ addFaceToken2FaceTokenSet(faceToken, facesetToken);
|
|
|
|
+
|
|
|
|
+ SaveStudentFaceInfoReq saveStudentFaceInfoReq = new SaveStudentFaceInfoReq();
|
|
|
|
+ saveStudentFaceInfoReq.setStudentId(student.getId());
|
|
|
|
+ saveStudentFaceInfoReq.setPhotoPath(photoPath);
|
|
|
|
+ saveStudentFaceInfoReq.setFaceToken(faceToken);
|
|
|
|
+ saveStudentFaceInfoReq.setFaceSetToken(facesetToken);
|
|
|
|
+
|
|
|
|
+ studentFaceCloudService.saveStudentFaceInfo(saveStudentFaceInfoReq);
|
|
}
|
|
}
|
|
|
|
+
|
|
}
|
|
}
|