一、技术选型
OCR服务:推荐使用百度AI
二、实现
1.注册一个服务
百度智能云控制台https://console.bce.baidu.com/ai-engine/ocr/overview/index?_=1742309417611
填写完之后可以获取到app-id、apiKey、SecretKey这三个后面文件配置会用到
2、导入依赖
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.13</version>
</dependency>
<!-- 百度AI SDK(示例) -->
<dependency>
<groupId>com.baidu.aip</groupId>
<artifactId>java-sdk</artifactId>
<version>4.16.13</version>
</dependency>
<!--json依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.40</version>
</dependency>
3、配置文件
spring:
servlet:
multipart:
max-request-size: 10MB # 文件上传最大值
max-file-size: 10MB # 单个文件最大值
baidu:
ai:
app-id: ***** 换成自己的
secret-key: ***** 换成自己的
api-key: ***** 换成自己的
4、编写OCR工具类
import com.baidu.aip.ocr.AipOcr;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
import java.util.Map;
@Component
public class OcrService {
@Value("${baidu.ai.app-id}")
private String appId;
@Value("${baidu.ai.api-key}")
private String apiKey;
@Value("${baidu.ai.secret-key}")
private String secretKey;
public Map<String, String> recognizeIdCard(MultipartFile file, boolean isFront) throws Exception {
AipOcr client = new AipOcr(appId, apiKey, secretKey);
// 读取图片字节
byte[] imgData = file.getBytes();
// 设置身份证正反面
String idCardSide = isFront ? "front" : "back";
// 设置其他识别选项(如果有)
HashMap<String, String> options = new HashMap<String, String>();
// 可以在这里添加其他选项,例如:
// options.put("detect_direction", "true"); // 检测图像朝向
// 调用身份证识别接口
JSONObject res = client.idcard(imgData, idCardSide, options);
// 检查返回结果
if (res == null || !res.has("words_result")) {
throw new Exception("OCR 识别失败: 返回结果为空或不包含 words_result");
}
// 解析结果
Map<String, String> result = new HashMap<String, String>();
JSONObject words = res.getJSONObject("words_result");
// 根据正反面提取不同字段
if (isFront) {
result.put("姓名", words.optString("姓名", ""));
result.put("性别", words.optString("性别", ""));
result.put("民族", words.optString("民族", ""));
result.put("出生日期", words.optString("出生年月日", ""));
result.put("住址", words.optString("住址", ""));
result.put("身份证号", words.optString("公民身份号码", ""));
} else {
result.put("签发机关", words.optString("签发机关", ""));
result.put("有效期限", words.optString("失效日期", ""));
}
return result;
}
}
5、文件上传接口
import com.alibaba.fastjson.JSON;
import com.cykj.service.OcrService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
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 java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/idcard")
/**
* 身份证识别控制器
* 提供身份证图片上传和识别功能
*/
public class IdCardController {
@Autowired
private OcrService ocrService;
/**
* 上传身份证图片并进行识别
*
* @param frontFile 身份证正面图片
* @param backFile 身份证反面图片
* @return 身份证信息的Map,包括正面和反面的识别结果
*/
@PostMapping("/upload")
public ResponseEntity<?> uploadIdCard(
@RequestParam("frontFile") MultipartFile frontFile,
@RequestParam("backFile") MultipartFile backFile) {
System.out.println(frontFile);
System.out.println(backFile);
try {
// 识别正面信息
Map<String, String> frontInfo = ocrService.recognizeIdCard(frontFile, true);
System.out.println("Front Info: " + frontInfo);
// 识别反面信息
Map<String, String> backInfo = ocrService.recognizeIdCard(backFile, false);
System.out.println("Back Info: " + backInfo);
// 合并结果
Map<String, String> combined = new HashMap<String, String>();
combined.putAll(frontInfo);
combined.putAll(backInfo);
// 身份证校验(示例)
String idNumberJson = combined.get("身份证号");
//解析获取身份证号
com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(idNumberJson);
String idNumber = jsonObject.getString("words");
if (!validateIdCard(idNumber)) {
return ResponseEntity.badRequest().body("身份证号校验失败");
}
return ResponseEntity.ok(combined);
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.status(500).body("识别失败: " + e.getMessage());
}
}
/**
* 简单身份证号校验(正则表达式)
*
* @param idNumber 身份证号码字符串
* @return 校验通过返回true,否则返回false
*/
private boolean validateIdCard(String idNumber) {
String regex = "^[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$";
return idNumber != null && idNumber.matches(regex);
}
}
三、前端写个测试页面
这边的action路径要改成自己的路径
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http://localhost:8086/api/idcard/upload" method="post" enctype="multipart/form-data">
<input type="file" name="frontFile" accept="image/*" required>
<input type="file" name="backFile" accept="image/*" required>
<button type="submit">上传并识别</button>
</form>
</body>
</html>
第一张为身份证正面(人)
第二张上传为身份证反面(国徽那面)
测试成功在页面和控制台都可以看见自己提取出来的信息就成功啦!