ai功能开发

This commit is contained in:
lizhenhua 2024-07-24 16:15:49 +08:00
parent 2018c54dbb
commit 995476dc34
7 changed files with 225 additions and 70 deletions

View File

@ -90,6 +90,10 @@
<groupId>com.bonus</groupId>
<artifactId>bonus-common-security</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
</dependencies>

View File

@ -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<IdCardVo> 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("数据上传失败!!!");
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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<String> 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<String> 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;
}
}

View File

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

View File

@ -3,6 +3,12 @@ server:
port: 18083
# Spring
spring:
servlet:
multipart:
# 文件最大
max-file-size: 20MB
# 设置总上传数据总大小
max-request-size: 20MB
application:
# 应用名称
name: bonus-ai