news 2026/4/3 3:49:34

SpringBoot集成DeepSeek-OCR实战|快速实现表格识别与结构化输出

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot集成DeepSeek-OCR实战|快速实现表格识别与结构化输出

SpringBoot集成DeepSeek-OCR实战|快速实现表格识别与结构化输出

1. 背景与业务场景

在企业级应用中,大量纸质单据如采购订单、发票、入库凭证等仍需人工录入系统。这一过程不仅效率低下,还容易因人为疏忽导致数据错误。随着AI技术的发展,光学字符识别(OCR)已成为自动化文档处理的核心工具。

DeepSeek-OCR 是由 DeepSeek 开源的一款高性能 OCR 大模型,具备强大的文本检测与识别能力,尤其擅长复杂场景下的表格、票据和公式识别。其 WebUI 版本提供了直观的可视化界面和标准 API 接口,便于快速集成到各类业务系统中。

本文将详细介绍如何通过SpringBoot后端服务调用本地部署的DeepSeek-OCR-WEBUI服务,完成对包含表格图像的识别,并将其结果解析为结构化的 JSON 数据,最终实现从前端上传 → 后端处理 → 结构化输出的完整流程。


2. 系统架构与技术选型

2.1 整体架构设计

整个系统的运行逻辑分为三层:

  • 前端层:基于 Vue 构建的用户操作界面,支持图片上传与结果显示
  • 后端服务层:SpringBoot 应用,负责接收请求、转发至 OCR 引擎并处理返回结果
  • OCR 引擎层:独立部署的 DeepSeek-OCR-WEBUI 容器服务,提供/ocr接口进行图像识别
[前端上传图片] ↓ [SpringBoot Controller] ↓ [HTTP POST → DeepSeek-OCR-WEBUI /ocr 接口] ↓ [返回HTML格式表格] ↓ [SpringBoot 解析为JSON] ↓ [返回给前端展示]

该架构实现了职责分离,保证了 OCR 引擎的高可用性与可扩展性,同时便于后期接入更多 AI 模型。

2.2 技术栈说明

层级技术组件
前端Vue 3 + Element Plus + Axios
后端SpringBoot 3.x + RestTemplate + Jackson
OCR引擎DeepSeek-OCR-WEBUI(Docker部署)
构建与部署Maven + Docker + docker-compose

3. 部署DeepSeek-OCR-WEBUI服务

在集成之前,必须确保DeepSeek-OCR-WEBUI已正确部署并正常运行。

3.1 启动OCR后端服务

进入项目目录并使用 Docker Compose 启动服务:

cd ~/DeepSeek-OCR-WebUI docker compose up -d

查看容器日志以确认服务启动成功:

docker logs -f deepseek-ocr-webui

服务默认监听http://localhost:8080,可通过浏览器访问 WebUI 页面进行测试。

⚠️ 注意:建议使用 NVIDIA GPU(如 4090D)运行该镜像以获得最佳性能,CPU 模式下推理速度较慢。


4. DeepSeek-OCR接口详解

OCR 服务暴露了一个核心接口用于图像识别:

@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) ):

4.1 关键参数说明

参数名类型可选值说明
file文件必填待识别的图像文件(JPG/PNG等)
prompt_type字符串document,ocr,free,figure,describe,find,freeform控制识别模式
find_term字符串可选查找特定关键词并标注位置
custom_prompt字符串可选自定义提示词,适用于复杂任务
grounding布尔值true/false是否启用实体定位分组

4.2 表格识别推荐配置

由于本文目标是识别表格内容,应选择prompt_type=figure,该模式专为图表、公式、表格设计,能更准确地保留原始布局信息。

例如发送请求时设置:

{ "prompt_type": "figure" }

响应体将返回一个标准 HTML<table>结构字符串,便于后续解析。


5. SpringBoot集成实现

5.1 创建OcrService接口

定义统一的服务接口,便于后续替换或扩展实现:

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

5.2 实现DeepSeekOcrService

创建具体实现类,使用RestTemplate发送 HTTP 请求至 OCR 服务。

// src/main/java/com/kaifamiao/dswebui/service/DeepSeekOcrService.java @Service @Slf4j public class DeepSeekOcrService implements OcrService { private static final String OCR_SERVICE_URL = "http://localhost:8080/ocr"; private final RestTemplate restTemplate; public DeepSeekOcrService() { this.restTemplate = new RestTemplate(); } @Override public Map<String, Object> recognitionTable(MultipartFile file) { log.info("开始识别表格图片: {}", file.getOriginalFilename()); try { // 准备文件资源 ByteArrayResource resource = new ByteArrayResource(file.getBytes()) { @Override public String getFilename() { return file.getOriginalFilename(); } }; // 构建请求参数 MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); body.add("file", resource); body.add("prompt_type", "figure"); // 使用图表模式识别表格 // 设置请求头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); // 创建请求实体 HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers); // 发送POST请求 ResponseEntity<String> response = restTemplate.postForEntity(OCR_SERVICE_URL, requestEntity, String.class); if (response.getStatusCode() == HttpStatus.OK) { String htmlContent = response.getBody(); log.debug("OCR返回HTML: {}", htmlContent); return parseHtmlTableToJSON(htmlContent); } else { log.error("OCR服务调用失败,状态码: {}", response.getStatusCode()); throw new RuntimeException("OCR识别失败"); } } catch (Exception e) { log.error("表格识别过程中发生异常", e); Map<String, Object> errorResult = new HashMap<>(); errorResult.put("success", false); errorResult.put("message", "识别失败:" + e.getMessage()); return errorResult; } } /** * 将HTML表格解析为JSON格式 * * @param html 包含表格的HTML字符串 * @return 转换后的JSON数据 */ private Map<String, Object> parseHtmlTableToJSON(String html) { Document doc = Jsoup.parse(html); Element table = doc.selectFirst("table"); List<Map<String, String>> rows = new ArrayList<>(); if (table != null) { Elements trList = table.select("tr"); for (Element tr : trList) { Elements tds = tr.select("td"); Map<String, String> row = new LinkedHashMap<>(); for (int i = 0; i < tds.size(); i++) { String text = tds.get(i).text().trim(); // 使用列索引作为key,也可提取表头做字段映射 row.put("col_" + i, text.isEmpty() ? "" : text); } rows.add(row); } } Map<String, Object> result = new HashMap<>(); result.put("success", true); result.put("data", rows); result.put("totalRows", rows.size()); return result; } }
依赖说明
  • RestTemplate:用于发起 HTTP 请求
  • Jsoup:轻量级 HTML 解析库,用于提取<table>内容
  • 添加依赖到pom.xml
<dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.16.1</version> </dependency>

5.3 编写单元测试验证功能

编写测试用例验证 OCR 服务是否正常工作。

// 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)); Assertions.assertTrue((Boolean) result.get("success")); } }

运行测试,观察日志输出是否成功解析出表格行数及内容。


5.4 提供REST API接口

创建控制器暴露 HTTP 接口供前端调用。

// 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> result = ocrService.recognitionTable(file); log.info("返回结果: {}", result); return result; } }

接口地址:POST /api/ocr/process,接受multipart/form-data格式的图片上传。


6. 前端页面集成

前端采用 Vue 实现简单上传界面,核心代码如下:

<template> <div class="container"> <h2>表格识别系统</h2> <input type="file" @change="handleFileChange" accept="image/*" /> <button @click="upload">上传识别</button> <div v-if="result"> <h3>识别结果(JSON):</h3> <pre>{{ JSON.stringify(result, null, 2) }}</pre> </div> </div> </template> <script setup> import { ref } from 'vue'; import axios from 'axios'; const file = ref(null); const result = ref(null); const handleFileChange = (e) => { file.value = e.target.files[0]; }; const upload = async () => { if (!file.value) { alert('请选择图片'); return; } const formData = new FormData(); formData.append('file', file.value); try { const res = await axios.post('/api/ocr/process', formData, { headers: { 'Content-Type': 'multipart/form-data' } }); result.value = res.data; } catch (err) { console.error(err); alert('识别失败'); } }; </script>

6.1 前端构建与打包

确保安装 Node.js 20+:

npm install npm run build

生成的dist目录需复制到 SpringBoot 的src/main/resources/static下,使静态资源可被直接访问。


7. 打包与Docker部署

7.1 后端打包

使用 Maven 构建 JAR 包:

mvn clean package -DskipTests

生成的文件位于target/deepseek-web-ui-1.0.0.jar


7.2 编写Dockerfile

# Java运行时阶段 FROM openjdk:21-jdk-slim # 设置工作目录 WORKDIR /app # 复制前端构建产物到后端静态资源目录 COPY target/deepseek-web-ui-1.0.0.jar /app/deepseek-web-ui.jar # 暴露端口 EXPOSE 8080 # 运行应用 ENTRYPOINT ["java", "-jar", "deepseek-web-ui.jar"]

7.3 编写docker-compose.yml

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

启动服务:

docker compose up -d --build

访问http://localhost:8080即可打开前端页面,上传表格图片进行识别。


8. 总结

本文详细介绍了如何将DeepSeek-OCR-WEBUI集成到SpringBoot应用中,实现对表格图像的自动识别与结构化输出。主要成果包括:

  1. ✅ 成功调用本地 OCR 服务 API 实现图像识别
  2. ✅ 将返回的 HTML 表格解析为标准 JSON 格式,便于前后端交互
  3. ✅ 构建完整的前后端联调系统,支持图片上传与结果展示
  4. ✅ 使用 Docker 完成一体化部署,提升可移植性与维护效率

该方案已在实际业务场景中验证有效,显著降低了人工录入成本,提升了数据处理效率。未来可进一步优化方向包括:

  • 支持多页PDF批量识别
  • 增加表头语义识别,自动映射数据库字段
  • 引入异步任务机制,避免长时间阻塞请求

通过本次实践,开发者可以快速掌握 AI OCR 技术在企业级 Java 应用中的落地方法,为智能化文档处理提供有力支撑。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/2 14:58:57

IQuest-Coder-V1实战案例:自动化代码重构工具开发保姆级教程

IQuest-Coder-V1实战案例&#xff1a;自动化代码重构工具开发保姆级教程 1. 引言&#xff1a;从大模型能力到工程落地的桥梁 1.1 背景与学习目标 在现代软件工程中&#xff0c;技术债务和代码腐化是长期困扰开发团队的核心问题。传统的手动重构方式效率低、易出错&#xff0…

作者头像 李华
网站建设 2026/4/2 10:29:58

手把手本地部署极速TTS系统|基于Supertonic镜像实现设备端语音合成

手把手本地部署极速TTS系统&#xff5c;基于Supertonic镜像实现设备端语音合成 1. 引言 1.1 业务场景描述 在当前AI语音交互日益普及的背景下&#xff0c;文本转语音&#xff08;TTS&#xff09;技术已成为智能助手、语音播报、无障碍阅读等应用的核心组件。然而&#xff0c…

作者头像 李华
网站建设 2026/3/25 2:33:44

Qwen3-4B vs InternLM2-5-7B:轻量模型综合性能对比

Qwen3-4B vs InternLM2-5-7B&#xff1a;轻量模型综合性能对比 1. 背景与选型动机 在当前大模型向端侧和边缘设备下沉的趋势下&#xff0c;轻量级高性能语言模型成为实际业务落地的关键。尤其是在推理成本敏感、部署环境受限的场景中&#xff08;如中小企业服务、本地化AI助手…

作者头像 李华
网站建设 2026/3/17 5:11:04

Supertonic实战案例:教育类应用的语音合成解决方案

Supertonic实战案例&#xff1a;教育类应用的语音合成解决方案 1. 背景与需求分析 1.1 教育类应用中的语音合成挑战 在现代教育技术的发展中&#xff0c;个性化学习和无障碍访问成为关键趋势。越来越多的学习平台开始集成语音功能&#xff0c;以支持听读结合的学习模式&…

作者头像 李华
网站建设 2026/4/1 21:14:43

Vllm云端开发指南:VSCode远程连接,像本地一样调试

Vllm云端开发指南&#xff1a;VSCode远程连接&#xff0c;像本地一样调试 你是不是也和我一样&#xff0c;习惯了在本地用 VSCode 写代码、打断点、看变量、实时调试&#xff1f;写 AI 模型服务的时候&#xff0c;总想一边改代码一边看输出&#xff0c;但一想到要上云、配环境…

作者头像 李华
网站建设 2026/3/27 6:29:21

Sharp-dumpkey:三分钟搞定微信数据库解密密钥提取

Sharp-dumpkey&#xff1a;三分钟搞定微信数据库解密密钥提取 【免费下载链接】Sharp-dumpkey 基于C#实现的获取微信数据库密钥的小工具 项目地址: https://gitcode.com/gh_mirrors/sh/Sharp-dumpkey 还在为无法查看微信聊天记录而烦恼吗&#xff1f;想要备份重要对话却…

作者头像 李华