diff --git a/bonus-modules/bonus-ai/pom.xml b/bonus-modules/bonus-ai/pom.xml index f339621..fc0f0c4 100644 --- a/bonus-modules/bonus-ai/pom.xml +++ b/bonus-modules/bonus-ai/pom.xml @@ -90,6 +90,10 @@ com.bonus bonus-common-security + + com.google.code.gson + gson + diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/OcrRecogController.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/OcrRecogController.java index 7d66aee..b56a8ab 100644 --- a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/OcrRecogController.java +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/controller/OcrRecogController.java @@ -1,16 +1,14 @@ package com.bonus.ai.controller; -//import com.bonus.ai.domain.IDCardInfo; -import com.bonus.ai.domain.dto.ImageUpload; -import com.bonus.ai.domain.po.AiIdcardrecognizeResult; -import com.bonus.ai.domain.vo.IdCardVo; import com.bonus.ai.service.IOcrRecogService; -import com.bonus.common.core.domain.R; +import com.bonus.ai.utils.FileTypeUtils; +import com.bonus.common.core.web.domain.AjaxResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; - -import java.util.List; +import static com.bonus.common.core.web.domain.AjaxResult.error; +import static com.bonus.common.core.web.domain.AjaxResult.success; /** * 文件请求处理 @@ -25,12 +23,24 @@ public class OcrRecogController private IOcrRecogService ocrRecogService; - @PostMapping("/recognition") - public R idCardRecognize( - @RequestBody ImageUpload imageUpload) { - return R.ok(ocrRecogService.detectIdCard(imageUpload)); +@PostMapping("/recognition") +public AjaxResult recognition(MultipartFile[] files, String type) { + AjaxResult ajax = AjaxResult.success(); + try { + for (MultipartFile file : files) { + String contentType = file.getContentType(); + if (!FileTypeUtils.FILE_TYPE_PNG.equals(contentType) && !FileTypeUtils.FILE_TYPE_JPEG.equals(contentType) && !FileTypeUtils.FILE_TYPE_PDF.equals(contentType)) { + return error("仅允许导入doc、jpg、png格式文件"); + } + } + ajax = ocrRecogService.recognitionCheck(files,type); + return success("数据上传成功!!!"); + } catch (Exception e) { + e.printStackTrace(); + return error("数据上传失败!!!"); } +} } diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/IdCardVo.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/IdCardVo.java index 4362c7d..b3d281e 100644 --- a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/IdCardVo.java +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/domain/vo/IdCardVo.java @@ -1,7 +1,6 @@ package com.bonus.ai.domain.vo; import lombok.Data; -import org.springframework.context.annotation.Configuration; @Data public class IdCardVo { @@ -18,5 +17,6 @@ public class IdCardVo { private String dateOfBirth; private String address; private String idNumber; + } } diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/IOcrRecogService.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/IOcrRecogService.java index 1478c11..78c0f3d 100644 --- a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/IOcrRecogService.java +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/IOcrRecogService.java @@ -1,7 +1,8 @@ package com.bonus.ai.service; -import com.bonus.ai.domain.dto.ImageUpload; -import com.bonus.ai.domain.vo.IdCardVo; +import com.bonus.common.core.web.domain.AjaxResult; +import org.springframework.web.multipart.MultipartFile; public interface IOcrRecogService { - IdCardVo detectIdCard(ImageUpload imageUpload); + + AjaxResult recognitionCheck(MultipartFile[] files, String type); } diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/OcrRecogServiceImpl.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/OcrRecogServiceImpl.java index 563f175..09f2216 100644 --- a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/OcrRecogServiceImpl.java +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/service/impl/OcrRecogServiceImpl.java @@ -5,73 +5,136 @@ import com.bonus.ai.domain.po.AiIdcardrecognizeResult; import com.bonus.ai.domain.vo.IdCardVo; import com.bonus.ai.mapper.AiIdcardrecognizeMapper; import com.bonus.ai.service.IOcrRecogService; +import com.bonus.common.core.utils.ServletUtils; +import com.bonus.common.core.utils.global.SystemGlobal; +import com.bonus.common.core.utils.ip.IpUtils; +import com.bonus.common.core.web.domain.AjaxResult; +import com.bonus.common.security.utils.SecurityUtils; +import com.bonus.system.api.model.LoginUser; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringEscapeUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; +import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; +import org.springframework.web.multipart.MultipartFile; import java.io.*; import java.nio.file.*; +import java.time.LocalDateTime; import java.util.*; + + + @Slf4j @Service public class OcrRecogServiceImpl implements IOcrRecogService { -// @Autowired -// private RestTemplate restTemplate; -// private final AiIdcardrecognizeResult aiIdcardrecognizeResult; + + private static final String FRONT_FILE_NAME_TEMPLATE = "%s_%s_front.jpg"; + private static final String BACK_FILE_NAME_TEMPLATE = "%s_%s_back.jpg"; + + + @Value("${idcard.record}") + private String recogurl; + + @Value("${idcard.directoryPath}") + private String directoryPath; + + @Autowired + private RestTemplate restTemplate; @Autowired private AiIdcardrecognizeMapper aiIdcardrecognizeMapper; - - @Override - public IdCardVo detectIdCard(ImageUpload imageUpload) { -// String recogUrl = "http://192.168.0.188:8080/recognition"; -// -// ResponseEntity response = restTemplate.postForEntity( -// recogUrl,imageUpload,String.class); -// String json = String.valueOf(response.getBody()); -// String json_deal= json.substring(1, json.length() - 1); - String response = "{\"code\": 20000, \"msg\": \"身份证信息完整\", \"data\": {\"issuingAuthority\": \"湘乡市公安局\", \"dateOfBirth\":\"2020.09.02\",\"validTime\": \"2020.09.02-2040.09.02\", \"name\": \"性#\", \"gender\": \"男\", \"ethnicity\": \"出生1964年11月30日\", \"dateOfBirth\": \"1964年11月30日\", \"address\": \"住地湖南省会同县广评镇西楼村三组6号\", \"idNumber\": \"43302919641130423X\"}}"; - - // 创建Gson实例,将python模型返回值赋值给前端对象 - Gson gson = new Gson(); - IdCardVo idCardVo = gson.fromJson(response, IdCardVo.class); - System.out.println(idCardVo); - - -// 保存数据 - char ifComplete = '否'; - if ("身份证信息完整".equals(idCardVo.getMsg())) { - ifComplete = '是'; - } - - String directoryPath = "C:\\images"; // 指定保存图片的目录 - String idNumber = idCardVo.getData().getIdNumber(); - String currentDate = LocalDate.now().toString(); - String frontFileName = idNumber + "_" + currentDate + "_front.jpg"; - String backFileName = idNumber + "_" + currentDate + "_back.jpg"; - byte[] frontImageBytes = Base64.getDecoder().decode(imageUpload.getRecognitionFrontData()); - byte[] backImageBytes = Base64.getDecoder().decode(imageUpload.getRecognitionBackData()); + public AjaxResult recognitionCheck(MultipartFile[] files, String type) { + AjaxResult ajax=null; + // 记录开始时间 + long startTime = System.currentTimeMillis(); + IdCardVo idCardVo = null; + String[] getfilePath = null; + //针对获取到的file转化base64 进行python调用 try { - Path frontFilePath = Paths.get(directoryPath, frontFileName); - Path backFilePath = Paths.get(directoryPath, backFileName); - Files.write(frontFilePath, frontImageBytes); // 将解码后的字节数组写入到文件中 - Files.write(backFilePath, backImageBytes); - System.out.println("图片保存成功:" + frontFilePath + backFilePath); - } catch (IOException e) { + getfilePath = convertFilesToBase64(files); + idCardVo = processPythonResponse(getfilePath, recogurl); + } catch (Exception e) { + ajax.put("601", "调用大模型服务出错"); e.printStackTrace(); - System.out.println("保存图片时出错:" + e.getMessage()); } + if (idCardVo != null) { + char ifComplete = '否'; + if (SystemGlobal.IDCARD_RECORD_SUCCESS.equals(idCardVo.getCode())) { + ifComplete = '是'; + } + String idNumber = idCardVo.getData().getIdNumber(); + String currentDate = System.currentTimeMillis()+""; + String frontFileName = String.format(FRONT_FILE_NAME_TEMPLATE, idNumber, currentDate); + String backFileName = String.format(BACK_FILE_NAME_TEMPLATE, idNumber, currentDate); + try { + byte[] frontImageBytes = Base64.getDecoder().decode(getfilePath[0]); + byte[] backImageBytes = Base64.getDecoder().decode(getfilePath[1]); + Path frontFilePath = Paths.get(directoryPath, frontFileName); + Path backFilePath = Paths.get(directoryPath, backFileName); + Files.write(frontFilePath, frontImageBytes); + Files.write(backFilePath, backImageBytes); + } catch (IOException e) { + ajax.put("602", "获取身份证信息出错"); + e.printStackTrace(); + } + saveRecognitionResult(idCardVo, ifComplete, frontFileName, backFileName,startTime); + } + return ajax; + } + + public String[] convertFilesToBase64(MultipartFile[] files) { + String[] base64Strings = new String[files.length]; + for (int i = 0; i < files.length; i++) { + MultipartFile file = files[i]; + try { + byte[] bytes = file.getBytes(); + String base64String = Base64.getEncoder().encodeToString(bytes); + base64Strings[i] = base64String; + } catch (IOException e) { + e.printStackTrace(); + } + } + return base64Strings; + } + + private IdCardVo processPythonResponse(String[] strings, String recogurl) throws Exception { + if (strings.length != 2) { + throw new IllegalArgumentException("Python响应数据不完整。"); + } + ImageUpload imageUpload = new ImageUpload(); + imageUpload.setRecognitionBackData(strings[0]); + imageUpload.setRecognitionFrontData(strings[1]); + imageUpload.setType("1"); + ResponseEntity response = restTemplate.postForEntity(recogurl, imageUpload, String.class); + if (response.getStatusCodeValue() != 200) { + throw new RestClientException("调用服务失败,状态码:" + response.getStatusCodeValue()); + } + String json = response.getBody(); + // 移除首尾字符 + json = json.substring(1, json.length() - 1); + // 解析转义字符 + json = StringEscapeUtils.unescapeJava(json); + Gson gson = new Gson(); + return gson.fromJson(json, IdCardVo.class); + } + private void saveRecognitionResult(IdCardVo idCardVo, char ifComplete, String frontFileName, String backFileName,long startTime) { + String idNumber = idCardVo.getData().getIdNumber(); + // 从SecurityUtils.getLoginUser()获取登录用户信息 + LoginUser loginUser = SecurityUtils.getLoginUser(); + // 记录结束时间 + long endTime = System.currentTimeMillis(); + // 计算响应时间 + long time = endTime - startTime; + int responseTime = (int) time; AiIdcardrecognizeResult aiIdcardrecognizeResult = AiIdcardrecognizeResult.builder() - .resultId(2L) .serviceId(1L) .name(idCardVo.getData().getName()) .sex(idCardVo.getData().getGender()) @@ -82,19 +145,15 @@ public class OcrRecogServiceImpl implements IOcrRecogService { .issuingAuthority(idCardVo.getData().getIssuingAuthority()) .idcardValidity(idCardVo.getData().getValidTime()) .ifComplete(ifComplete) - .frontImageAddress("a") - .backImageAddress("a") + .frontImageAddress(frontFileName) + .backImageAddress(backFileName) .recognizeTime(LocalDateTime.now()) - .responseLong(2) - .invokeIp("a") - .updateBy("a") + .responseLong(responseTime) + .invokeIp(IpUtils.getIpAddr(ServletUtils.getRequest())) + // .updateBy(loginUser.getUserid()) // 假设getUserid()已返回正确用户ID .updateTime(LocalDateTime.now()) - .delFlag('a') .build(); - System.out.println("最终结果:" + aiIdcardrecognizeResult); aiIdcardrecognizeMapper.insert(aiIdcardrecognizeResult); - - return idCardVo; - } + } diff --git a/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/utils/FileTypeUtils.java b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/utils/FileTypeUtils.java new file mode 100644 index 0000000..740f8ee --- /dev/null +++ b/bonus-modules/bonus-ai/src/main/java/com/bonus/ai/utils/FileTypeUtils.java @@ -0,0 +1,75 @@ +package com.bonus.ai.utils; + +import org.apache.commons.lang3.StringUtils; + +import java.io.File; + +/** + * 文件类型工具类 + * + * @author ruoyi + */ +public class FileTypeUtils { + public static final String FILE_TYPE_XLS = "application/vnd.ms-excel"; + public static final String FILE_TYPE_XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + public static final String FILE_TYPE_DOC = "application/msword"; + public static final String FILE_TYPE_DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; + public static final String FILE_TYPE_PDF = "application/pdf"; + public static final String FILE_TYPE_JSON = "application/json"; + public static final String FILE_TYPE_XML = "application/xml"; + public static final String FILE_TYPE_PNG = "image/png"; + public static final String FILE_TYPE_JPEG = "image/jpeg"; + public static final String FILE_TYPE_SVG = "image/svg"; + + /** + * 获取文件类型 + *

+ * 例如: ruoyi.txt, 返回: txt + * + * @param file 文件名 + * @return 后缀(不含".") + */ + public static String getFileType(File file) { + if (null == file) { + return StringUtils.EMPTY; + } + return getFileType(file.getName()); + } + + /** + * 获取文件类型 + *

+ * 例如: ruoyi.txt, 返回: txt + * + * @param fileName 文件名 + * @return 后缀(不含".") + */ + public static String getFileType(String fileName) { + int separatorIndex = fileName.lastIndexOf("."); + if (separatorIndex < 0) { + return ""; + } + return fileName.substring(separatorIndex + 1).toLowerCase(); + } + + /** + * 获取文件类型 + * + * @param photoByte 文件字节码 + * @return 后缀(不含".") + */ + public static String getFileExtendName(byte[] photoByte) { + String strFileExtendName = "JPG"; + if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) + && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) { + strFileExtendName = "GIF"; + } else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) { + strFileExtendName = "JPG"; + } else if ((photoByte[0] == 66) && (photoByte[1] == 77)) { + strFileExtendName = "BMP"; + } else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) { + strFileExtendName = "PNG"; + } + return strFileExtendName; + } +} \ No newline at end of file diff --git a/bonus-modules/bonus-ai/src/main/resources/bootstrap.yml b/bonus-modules/bonus-ai/src/main/resources/bootstrap.yml index 31204a7..a775e2d 100644 --- a/bonus-modules/bonus-ai/src/main/resources/bootstrap.yml +++ b/bonus-modules/bonus-ai/src/main/resources/bootstrap.yml @@ -3,6 +3,12 @@ server: port: 18083 # Spring spring: + servlet: + multipart: + # 文件最大 + max-file-size: 20MB + # 设置总上传数据总大小 + max-request-size: 20MB application: # 应用名称 name: bonus-ai