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

相关推荐
张np5 分钟前
java基础-Vector(向量)
java
光头程序员5 分钟前
学习笔记——常识解答之垃圾回收机制
java·笔记·学习
渡我白衣18 分钟前
并行的野心与现实——彻底拆解 C++ 标准并行算法(<execution>)的模型、陷阱与性能真相
java·开发语言·网络·c++·人工智能·windows·vscode
czlczl2002092519 分钟前
SpringBoot中web请求路径匹配的两种风格
java·前端·spring boot
bill44723 分钟前
BPMN2.0,flowable工作流指向多节点,并且只能选择其中一个节点的处理方式
java·工作流引擎·bpmn
Q_Q51100828524 分钟前
python+django/flask医药垃圾分类管理系统
spring boot·python·django·flask·node.js·php
2022.11.7始学前端26 分钟前
n8n第四节 表单触发器:让问卷提交自动触发企微消息推送
java·前端·数据库·n8n
Catcharlotte29 分钟前
异常(3)
java
岁岁种桃花儿31 分钟前
Java应用篇如何基于Redis共享Session实现短信登录
java·开发语言
资深低代码开发平台专家38 分钟前
通用编程时代正在向专用化分层演进
java·大数据·c语言·c++·python