复制代码
import ai.z.openapi.ZhipuAiClient;
import ai.z.openapi.service.layoutparsing.LayoutParsingCreateParams;
import ai.z.openapi.service.layoutparsing.LayoutParsingResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
/**
* GLM-OCR工具类
* 用于识别证书图片中的文字内容
*
* API文档:https://docs.bigmodel.cn/llms.txt
*/
@Slf4j
@Component
public class GLMOCRUtil {
@Value("${zhipu.ai.api-key}")
private String apiKey;
/**
* 使用GLM-OCR识别图片中的文字
*
* @param imageUrl OSS上的图片URL
* @return 识别的文字内容
*/
public String recognizeText(String imageUrl) {
try {
log.info("开始OCR识别,图片URL: {}", imageUrl);
// 1. 初始化客户端
ZhipuAiClient client = ZhipuAiClient.builder()
.ofZHIPU()
.apiKey(apiKey)
.build();
// 2. 设置模型
String model = "glm-ocr";
// 3. 创建布局解析请求
LayoutParsingCreateParams params = LayoutParsingCreateParams.builder()
.model(model)
.file(imageUrl)
.build();
// 4. 发送请求
LayoutParsingResponse response = client.layoutParsing().layoutParsing(params);
// 5. 处理响应
log.info("收到OCR响应,开始处理...");
log.info("响应是否成功: {}", response.isSuccess());
// 打印响应对象的详细信息
log.info("响应对象类型: {}", response.getClass().getName());
log.info("响应对象所有方法:");
for (java.lang.reflect.Method method : response.getClass().getMethods()) {
log.info(" - {} {}", method.getReturnType().getSimpleName(), method.getName());
}
if (response != null && response.isSuccess()) {
// 提取文字内容
String text = extractTextFromResponse(response);
if (text != null && !text.isEmpty()) {
log.info("OCR识别成功,识别到{}个字符", text.length());
log.debug("OCR识别内容预览: {}", text.length() > 200 ? text.substring(0, 200) + "..." : text);
return text;
} else {
log.warn("OCR识别结果为空");
// 即使结果为空,也尝试打印响应内容
log.warn("响应toString: {}", response.toString());
return "";
}
} else {
String msg = response != null ? response.getMsg() : "响应为空";
log.error("OCR识别失败: {}", msg);
throw new RuntimeException("OCR识别失败: " + msg);
}
} catch (Exception e) {
log.error("OCR识别异常", e);
throw new RuntimeException("OCR识别失败: " + e.getMessage(), e);
}
}
/**
* 从响应中提取文字内容
*
* 根据官方文档,响应包含 md_results 字段
*/
private String extractTextFromResponse(LayoutParsingResponse response) {
try {
log.info("开始提取OCR识别结果...");
log.info("响应类型: {}", response.getClass().getName());
// 尝试使用SDK提供的方法
// 根据官方文档,应该有 getMd_results() 方法
try {
// 方式1:直接调用getMd_results方法
java.lang.reflect.Method mdResultsMethod = response.getClass().getMethod("getMd_results");
Object mdResults = mdResultsMethod.invoke(response);
if (mdResults != null) {
String text = mdResults.toString();
log.info("通过getMd_results方法获取到OCR结果,长度: {}", text.length());
return text;
}
} catch (NoSuchMethodException e) {
log.warn("getMd_results方法不存在,尝试其他方法");
}
// 方式2:尝试getData方法
try {
java.lang.reflect.Method dataMethod = response.getClass().getMethod("getData");
Object data = dataMethod.invoke(response);
if (data != null) {
log.info("getData返回: {}", data.getClass().getName());
// 如果getData返回的是对象,尝试获取其md_results
try {
java.lang.reflect.Method dataMdMethod = data.getClass().getMethod("getMd_results");
Object dataMd = dataMdMethod.invoke(data);
if (dataMd != null) {
String text = dataMd.toString();
log.info("通过getData().getMd_results获取到OCR结果,长度: {}", text.length());
return text;
}
} catch (Exception ex) {
log.warn("getData().getMd_results失败: {}", ex.getMessage());
}
return data.toString();
}
} catch (NoSuchMethodException e) {
log.warn("getData方法不存在");
}
// 方式3:获取响应JSON字符串
try {
java.lang.reflect.Method toStringMethod = response.getClass().getMethod("toString");
Object strResult = toStringMethod.invoke(response);
log.info("响应toString结果: {}", strResult);
// 尝试从toString结果中解析
if (strResult != null && strResult.toString().contains("md_results")) {
// 简单解析JSON
String jsonStr = strResult.toString();
int mdIndex = jsonStr.indexOf("md_results");
if (mdIndex > 0) {
int startQuote = jsonStr.indexOf("\"", mdIndex + 11);
int endQuote = jsonStr.indexOf("\"", startQuote + 1);
if (startQuote > 0 && endQuote > startQuote) {
String text = jsonStr.substring(startQuote + 1, endQuote);
log.info("从toString解析到OCR结果,长度: {}", text.length());
return text;
}
}
}
} catch (Exception e) {
log.warn("解析toString失败: {}", e.getMessage());
}
log.error("所有提取方法都失败");
return null;
} catch (Exception e) {
log.error("提取OCR结果异常", e);
return null;
}
}
/**
* 使用GLM-OCR识别本地文件(Base64)
*
* @param imageBase64 图片Base64编码
* @return 识别的文字内容
*/
public String recognizeTextFromBase64(String imageBase64) {
try {
log.info("开始OCR识别(Base64方式),数据长度: {} bytes", imageBase64.length());
// 1. 初始化客户端
ZhipuAiClient client = ZhipuAiClient.builder()
.ofZHIPU()
.apiKey(apiKey)
.build();
// 2. 设置模型
String model = "glm-ocr";
// 3. 创建布局解析请求(使用Base64)
LayoutParsingCreateParams params = LayoutParsingCreateParams.builder()
.model(model)
.file(imageBase64)
.build();
// 4. 发送请求
LayoutParsingResponse response = client.layoutParsing().layoutParsing(params);
// 5. 处理响应
if (response != null && response.isSuccess()) {
// 提取文字内容
String text = extractTextFromResponse(response);
if (text != null && !text.isEmpty()) {
log.info("OCR识别成功,识别到{}个字符", text.length());
return text;
} else {
log.warn("OCR识别结果为空");
return "";
}
} else {
String msg = response != null ? response.getMsg() : "响应为空";
log.error("OCR识别失败: {}", msg);
throw new RuntimeException("OCR识别失败: " + msg);
}
} catch (Exception e) {
log.error("OCR识别异常", e);
throw new RuntimeException("OCR识别失败: " + e.getMessage(), e);
}
}
}