DeepSeek-OCR实战(06):SpringBoot应用接入

前一章部署了DeepSeek-OCR-WebUI ,它本身提供了API接口,这样在业务应用可以直接接入。本章将DeepSeek-OCR 接入到SpringBoot应用中,实现表格数据识别。

应用系统中通常会有一些单据需要入库,而入库单有些时候是纸质的,每条信息都录入费时费力,此时可以将单据使用手机对单据进行拍照,让应用识别提取,提取后人工进行校验,校验完毕一键入库。

1.启动DeepSeek-OCR-WebUI后端服务

要保证前一章节《DeepSeek-OCR实战(05):DeepSeek-OCR-WebUI部署(Docker)》 已经完整部署好。它提供了API接口。

shell 复制代码
cd ~/DeepSeek-OCR-WebUI
docker compose up -d 

# 查看docker日志
docker logs -f deepseek-ocr-webui

2.接口

代码:/home/qy/DeepSeek-OCR-WebUI/web_service.py

python 复制代码
@app.post("/ocr")
async def ocr_endpoint(
    file: UploadFile = File(...),
    prompt_type: str = Form("document"),
    find_term: str = Form(""),
    custom_prompt: str = Form(""),
    grounding: bool = Form(False)
):
  • 上传的图片文件
  • prompt_type:可传入的值有
    • document : 文档转Markdown,保留格式和布局,适用场景:合同、论文、报告
    • ocr: 通用OCR,提取所有可见文字, 适用场景:图片文字提取
    • free: 纯文本提取,纯文本不保留格式,适用场景:简单文本识别
    • figure: 图表解析,识别图表和公式,适用场景:数据图表、数学公式。 本章就是要识别表格,所以使用这个参数
    • describe:图像描述,生成详细描述,适用场景:图片理解、无障碍
    • find: 查找定位,查找并标注位置,适用场景:发票字段定位
    • freeform: 自定义提示词,自定义识别需求。适用场景:灵活的识别任务
  • find_term: 要查找/标注的信息
  • custom_prompt: 自定义提示词
  • grounding :分组

如果要扩展这个接口,可以直接修改/home/qy/DeepSeek-OCR-WebUI/web_service.py Python代码。但是修改完毕之后,要重新build镜像

3.SpringBoot接入

API服务已经启动,SpringBoot接入的方式就是发送Http请求给DeepSeek-OCR-WebUI 接口获取数据。本节目的很明确,就是要识别表格。API 返回的是 HTML代码。SpringBoot拿到HTML代码后,将数据转换为 JSON格式,HTML代码结构如下:

html 复制代码
<table><tr><td>序号</td><td>条码</td><td>名称</td><td>单位</td><td>订货数量</td><td>采购数量</td><td>赠送数量</td><td>采购单价</td><td>金额小计</td><td>备注</td></tr><tr><td>1</td><td>6949123352617</td><td>飞科PR-5261毛球修剪器</td><td>个</td><td>0.00</td><td>1.00</td><td>0.00</td><td>38.5000</td><td>38.5000</td><td></td></tr><tr><td>2</td><td>6944296500049</td><td>天香炸酱面180g*50</td><td>个</td><td>0.00</td><td>1.00</td><td>0.00</td><td>0.0000</td><td>0.0000</td><td></td></tr><tr><td>3</td><td>6901826260159</td><td>南孚NF-1620锂电子</td><td>粒</td><td>0.00</td><td>0.00</td><td>1.00</td><td>2.4000</td><td>0.0000</td><td></td></tr><tr><td>总计</td><td></td><td></td><td></td><td>0.00</td><td>2.00</td><td>1.00</td><td>0.0000</td><td>38.5000</td><td></td></tr></table>

3.1 OcrService接口

java 复制代码
// src/main/java/com/kaifamiao/dswebui/service/OcrService.java
public interface OcrService {

    /**
     * 识别表格图片并返回结构化数据
     *
     * @param file 上传的包含表格的图片文件
     * @return 包含表格数据的Map对象,将以JSON格式返回给前端
     */
    Map<String, Object> recognitionTable(MultipartFile file);
}

3.2接口实现

详情请访问文末代码仓库地址获取

java 复制代码
//src/main/java/com/kaifamiao/dswebui/service/DeepSeekOcrService.java
@Service
@Slf4j
public class DeepSeekOcrService implements OcrService {
    @Override
    public Map<String, Object> recognitionTable(MultipartFile file) {
        log.info("name===>{}", file.getOriginalFilename());
        try {
            // 创建RestTemplate实例
            ...

            // 准备文件资源
            ...

            // 准备请求参数
            ...

            // 设置请求头
            ...

            // 创建请求实体
            ...

            // 发送POST请求到OCR服务
            ...

            // 解析HTML表格并转换为JSON
            return parseHtmlTableToJSON(responseHtml);
        } catch (Exception e) {
           ...
        }
    }

    /**
     * 将HTML表格解析为JSON格式
     *
     * @param html 包含表格的HTML字符串
     * @return 转换后的JSON数据
     */
    private Map<String, Object> parseHtmlTableToJSON(String html) {
        ...
        return result;
    }

}

写个测试用例测试一下,将要测试的图片放到 src/test/resources/voucher.jpg

java 复制代码
// src/test/java/com/kaifamiao/dswebui/service/OcrServiceTest.java
@SpringBootTest
@Slf4j
public class OcrServiceTest {
    @Autowired
    private OcrService ocrService;
    @Test
    void testRecognitionTableSuccess() throws Exception {
        // 从测试资源目录加载voucher.jpg文件
        ClassPathResource resource = new ClassPathResource("voucher.jpg");
        // 创建MultipartFile对象
        MockMultipartFile file = new MockMultipartFile(
                "file",
                "voucher.jpg",
                "image/jpeg",
                resource.getInputStream()
        );

        // 调用OCR服务进行识别
        Map<String, Object> result = ocrService.recognitionTable(file);

        log.info("OCR识别结果: {}", JSON.toJSONString(result));
    }

}

3.3Controller

java 复制代码
// src/main/java/com/kaifamiao/dswebui/controller/OcrController.java

@RestController
@RequestMapping("/api/ocr")
@Slf4j
public class OcrController {

    @Autowired
    private OcrService ocrService;

    @PostMapping("/process")
    public Map<String, Object> processFile(@RequestParam("file") MultipartFile file) {
        Map<String, Object> stringObjectMap = ocrService.recognitionTable(file);
        log.info("result===>{}", stringObjectMap);
        return stringObjectMap;
    }
}

4.前端页面

项目有个ui是使用VUE写的一个操作界面。 自行查看代码。

编译打包:要安装NodeJS 20 以上版本。

shell 复制代码
npm i
npm run build

将生成的dist 下文件拷贝到SpringBoot项目中

5.后端打包

6.docker启动

shell 复制代码
# Dockerfile
# Java运行时阶段
FROM openjdk:21-jdk-slim

# 设置工作目录
WORKDIR /app

# 复制前端构建产物到后端静态资源目录
COPY deepseek-webui/target/deepseek-web-ui-1.0.0.jar /app/deepseek-web-ui.jar

# 暴露端口
EXPOSE 8080

# 运行应用
ENTRYPOINT ["java", "-jar", "deepseek-web-ui.jar"]
shell 复制代码
# docker-compose.yml
version: '3.8'

services:
  ocr-app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - SERVER_PORT=8080
    volumes:
      - ./logs:/app/logs

准备好docker 环境:

shell 复制代码
docker compose up -d --build

源代码地址: https://github.com/kaiwill/kaifamiao-ocr

相关推荐
せいしゅん青春之我2 小时前
【JavaEE初阶】IP协议-IP地址不够用了咋办?
java·服务器·网络·网络协议·tcp/ip·java-ee
醇氧2 小时前
MAC 安装openJDK8
java·开发语言
海阔天空在前走2 小时前
JAVA中六种策略模式的实现
java·开发语言·策略模式
Slow菜鸟2 小时前
Java后端常用技术选型 |(五)可视化工具篇
java
青衫码上行2 小时前
【Java Web学习 | 第十篇】JavaScript(4) 对象
java·开发语言·前端·javascript·学习
q***69772 小时前
快速在本地运行SpringBoot项目的流程介绍
java·spring boot·后端
q***42822 小时前
前端的dist包放到后端springboot项目下一起打包
前端·spring boot·后端
随缘体验官2 小时前
【无标题】测试一下
java
.柒宇.2 小时前
力扣hoT100之找到字符串中所有字母异位词(java版)
java·数据结构·算法·leetcode