|
@@ -1,5 +1,25 @@
|
|
|
package cn.com.qmth.examcloud.exchange.outer.api.provider;
|
|
|
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.List;
|
|
|
+import java.util.zip.ZipEntry;
|
|
|
+import java.util.zip.ZipInputStream;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+
|
|
|
+import org.apache.commons.io.output.ByteArrayOutputStream;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.http.HttpStatus;
|
|
|
+import org.springframework.http.ResponseEntity;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
+import org.springframework.web.bind.annotation.PostMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestParam;
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
+
|
|
|
+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.web.security.bean.User;
|
|
|
import cn.com.qmth.examcloud.commons.web.support.ControllerSupport;
|
|
@@ -13,213 +33,210 @@ import cn.com.qmth.examcloud.exchange.outer.service.FaceppService;
|
|
|
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.impl.UpyunServiceImpl;
|
|
|
-import cn.com.qmth.examcloud.common.dto.core.StudentFaceInfo;
|
|
|
-import cn.com.qmth.examcloud.common.dto.em.ExamStudent;
|
|
|
-
|
|
|
-import org.apache.commons.io.output.ByteArrayOutputStream;
|
|
|
-import org.slf4j.Logger;
|
|
|
-import org.slf4j.LoggerFactory;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.http.HttpStatus;
|
|
|
-import org.springframework.http.ResponseEntity;
|
|
|
-import org.springframework.util.StringUtils;
|
|
|
-import org.springframework.web.bind.annotation.PostMapping;
|
|
|
-import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
-import org.springframework.web.bind.annotation.RequestParam;
|
|
|
-import org.springframework.web.bind.annotation.RestController;
|
|
|
-import org.springframework.web.multipart.MultipartFile;
|
|
|
-
|
|
|
-import javax.servlet.http.HttpServletRequest;
|
|
|
-
|
|
|
-import java.io.IOException;
|
|
|
-import java.util.List;
|
|
|
-import java.util.zip.ZipEntry;
|
|
|
-import java.util.zip.ZipInputStream;
|
|
|
|
|
|
/**
|
|
|
* 学生照片接口
|
|
|
- * @author chenken
|
|
|
- * @date 2018年4月3日 下午3:58:31
|
|
|
- * @company QMTH
|
|
|
+ *
|
|
|
+ * @author chenken
|
|
|
+ * @date 2018年4月3日 下午3:58:31
|
|
|
+ * @company QMTH
|
|
|
* @description FaceppController.java
|
|
|
*/
|
|
|
@RestController
|
|
|
@RequestMapping("${$rmp.cloud.exchange.outer}/facepp")
|
|
|
-public class FaceppController extends ControllerSupport{
|
|
|
-
|
|
|
- private static final Logger LOG = LoggerFactory.getLogger(FaceppController.class);
|
|
|
-
|
|
|
- /**
|
|
|
- * ZIP最大50M
|
|
|
- */
|
|
|
- private static final int ZIP_MAX_SIZE = 50;
|
|
|
- /**
|
|
|
- * 最大张数500张
|
|
|
- */
|
|
|
- private static final int MAX_COUNT = 500;
|
|
|
- /**
|
|
|
- * 每张照片最大尺寸 500KB
|
|
|
- */
|
|
|
- private static final int MAX_SIZE = 500;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private ExamStudentClient examStudentClient;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private UpyunServiceImpl upyunService;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private FaceppService faceppService;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private StudentFaceInfoClient studentFaceInfoClient;
|
|
|
-
|
|
|
- /**
|
|
|
- * 单个上传
|
|
|
- * @param file
|
|
|
- * @param request
|
|
|
- * @return
|
|
|
- */
|
|
|
- @PostMapping("/add")
|
|
|
- public ResponseEntity<IBaseResponse> add(@RequestParam MultipartFile file, HttpServletRequest request) {
|
|
|
- User accessUser = getAccessUser();
|
|
|
- if (accessUser == null) {
|
|
|
- return new ResponseEntity<>(new FailureBaseResponse("请先登录", null), HttpStatus.BAD_REQUEST);
|
|
|
- }
|
|
|
- try {
|
|
|
- LOG.info("fileName = {}", file.getOriginalFilename());
|
|
|
- faceppService.processOne(accessUser,file.getOriginalFilename(), file.getBytes(), accessUser.getRootOrgId());
|
|
|
- return new ResponseEntity<>(new SuccessBaseResponse("上传成功", null),HttpStatus.OK);
|
|
|
- } catch (InvalidJpgException e) {
|
|
|
- e.printStackTrace();
|
|
|
- return new ResponseEntity<>(new FailureBaseResponse("不是一个图片文件",null), HttpStatus.NOT_ACCEPTABLE);
|
|
|
- } catch (ExamStudentNotExistException e) {
|
|
|
- e.printStackTrace();
|
|
|
- return new ResponseEntity<>(new FailureBaseResponse("考生不存在",null), HttpStatus.NOT_ACCEPTABLE);
|
|
|
- } catch (DetectNoFaceException e) {
|
|
|
- e.printStackTrace();
|
|
|
- return new ResponseEntity<>(new FailureBaseResponse("检测不到人脸",null), HttpStatus.NOT_ACCEPTABLE);
|
|
|
- } catch (Exception e) {
|
|
|
- e.printStackTrace();
|
|
|
- return new ResponseEntity<>(new FailureBaseResponse("上传失败",null), HttpStatus.INTERNAL_SERVER_ERROR);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 学生照片打包成ZIP文件批量上传
|
|
|
- * @param file
|
|
|
- * @param request
|
|
|
- * @return
|
|
|
- * @throws Exception
|
|
|
- */
|
|
|
- @PostMapping("/import")
|
|
|
- public ResponseEntity<IBaseResponse> batchAllFace(@RequestParam MultipartFile file, HttpServletRequest request) throws Exception {
|
|
|
- User accessUser = getAccessUser();
|
|
|
- if (accessUser == null) {
|
|
|
- return new ResponseEntity<>(new FailureBaseResponse("请先登录", null), HttpStatus.BAD_REQUEST);
|
|
|
- }
|
|
|
- String userToken = accessUser.getToken();
|
|
|
- Long rootOrgId = accessUser.getRootOrgId();
|
|
|
-
|
|
|
- if (!file.getOriginalFilename().endsWith(".zip")) {
|
|
|
- return new ResponseEntity<>(new FailureBaseResponse("文件格式不正确,必须是zip格式的压缩包", null), HttpStatus.BAD_REQUEST);
|
|
|
- }
|
|
|
- //文件大小限制
|
|
|
- if (file.getSize() > ZIP_MAX_SIZE * 1024 * 1024) {
|
|
|
- return new ResponseEntity<>(new FailureBaseResponse("文件大小超过50M,请分批导入", null), HttpStatus.BAD_REQUEST);
|
|
|
- }
|
|
|
- ZipInputStream zin = new ZipInputStream(file.getInputStream());
|
|
|
- ZipEntry ze;
|
|
|
- //一次最多处理10个照片
|
|
|
- int count = 0;
|
|
|
- String identityNumber = "";
|
|
|
- String suffix = "";
|
|
|
- try {
|
|
|
- while ((ze = zin.getNextEntry()) != null && count < MAX_COUNT) {
|
|
|
- if (!ze.isDirectory()) {
|
|
|
- count++;
|
|
|
- if (ze.getSize() > MAX_SIZE * 1024) {
|
|
|
- throw new InvalidJpgException(ze.getName() + "超过了" + MAX_SIZE + "KB,请压缩后上传");
|
|
|
- }
|
|
|
- //计算出身份证号
|
|
|
- String[] nameAndSuffix = ze.getName().split("\\.");
|
|
|
- if (nameAndSuffix.length < 2) {
|
|
|
- throw new InvalidJpgException(ze.getName() + "不是一个照片文件");
|
|
|
- }
|
|
|
- identityNumber = (nameAndSuffix[0].startsWith("/") || nameAndSuffix[0].startsWith("\\")) ? nameAndSuffix[0].substring(1) : nameAndSuffix[0];
|
|
|
- suffix = nameAndSuffix[1];
|
|
|
- LOG.info("文件名为 :" + identityNumber + ",后缀名为:" + suffix);
|
|
|
- //根据身份证号码,查询考生是否存在
|
|
|
- LOG.info("查询身份证号码为 :" + identityNumber + "的学生");
|
|
|
- String json = examStudentClient.getExamStudentByIdentityNumber(userToken, identityNumber);
|
|
|
- if (StringUtils.isEmpty(json)) {
|
|
|
- LOG.error("身份证号为:" + identityNumber + "的考生不存在");
|
|
|
- continue;
|
|
|
- } else {
|
|
|
- List<ExamStudent> examStudentList = GsonUtil.jsonToArrayList(json, ExamStudent.class);
|
|
|
- if (examStudentList.size() < 1) {
|
|
|
- LOG.error("身份证号为:" + identityNumber + "的考生不存在");
|
|
|
- //如果找不到学生信息,则跳过
|
|
|
- continue;
|
|
|
- }
|
|
|
- ExamStudent examStudent = examStudentList.get(0);
|
|
|
- ByteArrayOutputStream output = new ByteArrayOutputStream();
|
|
|
- //保存学生照片到又拍云
|
|
|
- int len = -1;
|
|
|
- byte[] bytes = new byte[4096];
|
|
|
- while ((len = zin.read(bytes)) != -1) {
|
|
|
- output.write(bytes, 0, len);
|
|
|
- }
|
|
|
- output.close();
|
|
|
- byte[] dataBytes = output.toByteArray();
|
|
|
- String fileName = upyunService.getMd5(dataBytes);
|
|
|
- if (upyunService.saveStudentPhoto(identityNumber,dataBytes,fileName,"." + suffix)) {
|
|
|
- LOG.info("保存" + identityNumber + "的照片到又拍云成功");
|
|
|
- //调用人脸识别接口
|
|
|
- String faceToken = null;
|
|
|
- try {
|
|
|
- faceToken = faceppService.detectSingleFace(upyunService.getDownloadUrl(identityNumber, fileName, "." + suffix));
|
|
|
- } catch (DetectNoFaceException e) {
|
|
|
- LOG.error(identityNumber + "检测人脸失败");
|
|
|
- continue;
|
|
|
- }
|
|
|
- ResponseEntity<StudentFaceInfo> studentFaceInfoResponseEntity = studentFaceInfoClient.getByIdentityNumber(userToken, identityNumber, rootOrgId);
|
|
|
- StudentFaceInfo studentFaceInfo = studentFaceInfoResponseEntity.getBody();
|
|
|
- //获取faceSet,并将faceToken添加进facesetToken
|
|
|
- String facesetToken = studentFaceInfoClient.getFaceSet();
|
|
|
- if (faceppService.addFace(faceToken, facesetToken)){
|
|
|
- String photoMD5 = fileName+"."+suffix;
|
|
|
- faceppService.saveStudentFaceInfo(studentFaceInfo,
|
|
|
- photoMD5,
|
|
|
- faceToken,
|
|
|
- facesetToken,
|
|
|
- examStudent.getStudentId(),
|
|
|
- accessUser.getDisplayName(),
|
|
|
- "INTERFACE_IMPORT",
|
|
|
- userToken);
|
|
|
- } else {
|
|
|
- LOG.error(identityNumber + "添加照片到人脸集合失败");
|
|
|
- continue;
|
|
|
- }
|
|
|
- } else {
|
|
|
- LOG.error("身份证号为:" + identityNumber + "的考生照片保存到又拍云失败");
|
|
|
- continue;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (InvalidJpgException e) {
|
|
|
- LOG.error("导入照片出现格式错误:", e);
|
|
|
- return new ResponseEntity<>(new FailureBaseResponse(e.getMessage(), identityNumber), HttpStatus.BAD_REQUEST);
|
|
|
- }
|
|
|
- catch (IOException e) {
|
|
|
- LOG.error("导入照片出现IO错误:", e);
|
|
|
- return new ResponseEntity<>(new FailureBaseResponse(e.getMessage(), identityNumber), HttpStatus.INTERNAL_SERVER_ERROR);
|
|
|
- } finally {
|
|
|
- zin.closeEntry();
|
|
|
- }
|
|
|
- return new ResponseEntity<>(HttpStatus.OK);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
+public class FaceppController extends ControllerSupport {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * ZIP最大50M
|
|
|
+ */
|
|
|
+ private static final int ZIP_MAX_SIZE = 50;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 最大张数500张
|
|
|
+ */
|
|
|
+ private static final int MAX_COUNT = 500;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 每张照片最大尺寸 500KB
|
|
|
+ */
|
|
|
+ private static final int MAX_SIZE = 500;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ExamStudentClient examStudentClient;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private UpyunServiceImpl upyunService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private FaceppService faceppService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private StudentFaceInfoClient studentFaceInfoClient;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 单个上传
|
|
|
+ *
|
|
|
+ * @param file
|
|
|
+ * @param request
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @PostMapping("/add")
|
|
|
+ public ResponseEntity<IBaseResponse> add(@RequestParam MultipartFile file,
|
|
|
+ HttpServletRequest request) {
|
|
|
+ User accessUser = getAccessUser();
|
|
|
+ if (accessUser == null) {
|
|
|
+ return new ResponseEntity<>(new FailureBaseResponse("请先登录", null),
|
|
|
+ HttpStatus.BAD_REQUEST);
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ log.info("fileName = {}" + file.getOriginalFilename());
|
|
|
+ faceppService.processOne(accessUser, file.getOriginalFilename(), file.getBytes(),
|
|
|
+ accessUser.getRootOrgId());
|
|
|
+ return new ResponseEntity<>(new SuccessBaseResponse("上传成功", null), HttpStatus.OK);
|
|
|
+ } catch (InvalidJpgException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ return new ResponseEntity<>(new FailureBaseResponse("不是一个图片文件", null),
|
|
|
+ HttpStatus.NOT_ACCEPTABLE);
|
|
|
+ } catch (ExamStudentNotExistException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ return new ResponseEntity<>(new FailureBaseResponse("考生不存在", null),
|
|
|
+ HttpStatus.NOT_ACCEPTABLE);
|
|
|
+ } catch (DetectNoFaceException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ return new ResponseEntity<>(new FailureBaseResponse("检测不到人脸", null),
|
|
|
+ HttpStatus.NOT_ACCEPTABLE);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ return new ResponseEntity<>(new FailureBaseResponse("上传失败", null),
|
|
|
+ HttpStatus.INTERNAL_SERVER_ERROR);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 学生照片打包成ZIP文件批量上传
|
|
|
+ *
|
|
|
+ * @param file
|
|
|
+ * @param request
|
|
|
+ * @return
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
+ @PostMapping("/import")
|
|
|
+ public ResponseEntity<IBaseResponse> batchAllFace(@RequestParam MultipartFile file,
|
|
|
+ HttpServletRequest request) throws Exception {
|
|
|
+ User accessUser = getAccessUser();
|
|
|
+ if (accessUser == null) {
|
|
|
+ return new ResponseEntity<>(new FailureBaseResponse("请先登录", null),
|
|
|
+ HttpStatus.BAD_REQUEST);
|
|
|
+ }
|
|
|
+ String userToken = accessUser.getToken();
|
|
|
+ Long rootOrgId = accessUser.getRootOrgId();
|
|
|
+
|
|
|
+ if (!file.getOriginalFilename().endsWith(".zip")) {
|
|
|
+ return new ResponseEntity<>(new FailureBaseResponse("文件格式不正确,必须是zip格式的压缩包", null),
|
|
|
+ HttpStatus.BAD_REQUEST);
|
|
|
+ }
|
|
|
+ // 文件大小限制
|
|
|
+ if (file.getSize() > ZIP_MAX_SIZE * 1024 * 1024) {
|
|
|
+ return new ResponseEntity<>(new FailureBaseResponse("文件大小超过50M,请分批导入", null),
|
|
|
+ HttpStatus.BAD_REQUEST);
|
|
|
+ }
|
|
|
+ ZipInputStream zin = new ZipInputStream(file.getInputStream());
|
|
|
+ ZipEntry ze;
|
|
|
+ // 一次最多处理10个照片
|
|
|
+ int count = 0;
|
|
|
+ String identityNumber = "";
|
|
|
+ String suffix = "";
|
|
|
+ try {
|
|
|
+ while ((ze = zin.getNextEntry()) != null && count < MAX_COUNT) {
|
|
|
+ if (!ze.isDirectory()) {
|
|
|
+ count++;
|
|
|
+ if (ze.getSize() > MAX_SIZE * 1024) {
|
|
|
+ throw new InvalidJpgException(
|
|
|
+ ze.getName() + "超过了" + MAX_SIZE + "KB,请压缩后上传");
|
|
|
+ }
|
|
|
+ // 计算出身份证号
|
|
|
+ String[] nameAndSuffix = ze.getName().split("\\.");
|
|
|
+ if (nameAndSuffix.length < 2) {
|
|
|
+ throw new InvalidJpgException(ze.getName() + "不是一个照片文件");
|
|
|
+ }
|
|
|
+ identityNumber = (nameAndSuffix[0].startsWith("/")
|
|
|
+ || nameAndSuffix[0].startsWith("\\"))
|
|
|
+ ? nameAndSuffix[0].substring(1)
|
|
|
+ : nameAndSuffix[0];
|
|
|
+ suffix = nameAndSuffix[1];
|
|
|
+ log.info("文件名为 :" + identityNumber + ",后缀名为:" + suffix);
|
|
|
+ // 根据身份证号码,查询考生是否存在
|
|
|
+ log.info("查询身份证号码为 :" + identityNumber + "的学生");
|
|
|
+ String json = examStudentClient.getExamStudentByIdentityNumber(userToken,
|
|
|
+ identityNumber);
|
|
|
+ if (StringUtils.isEmpty(json)) {
|
|
|
+ log.error("身份证号为:" + identityNumber + "的考生不存在");
|
|
|
+ continue;
|
|
|
+ } else {
|
|
|
+ List<ExamStudent> examStudentList = GsonUtil.jsonToArrayList(json,
|
|
|
+ ExamStudent.class);
|
|
|
+ if (examStudentList.size() < 1) {
|
|
|
+ log.error("身份证号为:" + identityNumber + "的考生不存在");
|
|
|
+ // 如果找不到学生信息,则跳过
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ ExamStudent examStudent = examStudentList.get(0);
|
|
|
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
|
|
|
+ // 保存学生照片到又拍云
|
|
|
+ int len = -1;
|
|
|
+ byte[] bytes = new byte[4096];
|
|
|
+ while ((len = zin.read(bytes)) != -1) {
|
|
|
+ output.write(bytes, 0, len);
|
|
|
+ }
|
|
|
+ output.close();
|
|
|
+ byte[] dataBytes = output.toByteArray();
|
|
|
+ String fileName = upyunService.getMd5(dataBytes);
|
|
|
+ if (upyunService.saveStudentPhoto(identityNumber, dataBytes, fileName,
|
|
|
+ "." + suffix)) {
|
|
|
+ log.info("保存" + identityNumber + "的照片到又拍云成功");
|
|
|
+ // 调用人脸识别接口
|
|
|
+ String faceToken = null;
|
|
|
+ try {
|
|
|
+ faceToken = faceppService.detectSingleFace(upyunService
|
|
|
+ .getDownloadUrl(identityNumber, fileName, "." + suffix));
|
|
|
+ } catch (DetectNoFaceException e) {
|
|
|
+ log.error(identityNumber + "检测人脸失败");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ ResponseEntity<StudentFaceInfo> studentFaceInfoResponseEntity = studentFaceInfoClient
|
|
|
+ .getByIdentityNumber(userToken, identityNumber, rootOrgId);
|
|
|
+ StudentFaceInfo studentFaceInfo = studentFaceInfoResponseEntity
|
|
|
+ .getBody();
|
|
|
+ // 获取faceSet,并将faceToken添加进facesetToken
|
|
|
+ String facesetToken = studentFaceInfoClient.getFaceSet();
|
|
|
+ if (faceppService.addFace(faceToken, facesetToken)) {
|
|
|
+ String photoMD5 = fileName + "." + suffix;
|
|
|
+ faceppService.saveStudentFaceInfo(studentFaceInfo, photoMD5,
|
|
|
+ faceToken, facesetToken, examStudent.getStudentId(),
|
|
|
+ accessUser.getDisplayName(), "INTERFACE_IMPORT", userToken);
|
|
|
+ } else {
|
|
|
+ log.error(identityNumber + "添加照片到人脸集合失败");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ log.error("身份证号为:" + identityNumber + "的考生照片保存到又拍云失败");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (InvalidJpgException e) {
|
|
|
+ log.error("导入照片出现格式错误:", e);
|
|
|
+ return new ResponseEntity<>(new FailureBaseResponse(e.getMessage(), identityNumber),
|
|
|
+ HttpStatus.BAD_REQUEST);
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error("导入照片出现IO错误:", e);
|
|
|
+ return new ResponseEntity<>(new FailureBaseResponse(e.getMessage(), identityNumber),
|
|
|
+ HttpStatus.INTERNAL_SERVER_ERROR);
|
|
|
+ } finally {
|
|
|
+ zin.closeEntry();
|
|
|
+ }
|
|
|
+ return new ResponseEntity<>(HttpStatus.OK);
|
|
|
+ }
|
|
|
+
|
|
|
}
|