Spring Boot 实现 DOCX 转 PDF(基于 docx4j 的轻量级开源方案) - 教程

news/2025/11/18 15:45:10/文章来源:https://www.cnblogs.com/gccbuaa/p/19238102

目录

  • 一、方案选型对比
  • 二、添加 Maven 依赖
  • 三、核心工具类:DocxToPdfUtil
  • 四、Controller 示例
  • 五、Windows解决中文乱码问题
  • 六、Linux解决中文乱码问题
  • 七、总结

在日常项目开发中,我们经常遇到这样的需求:
用户上传 Word( .docx)文件,希望后台自动生成 PDF,用于下载、归档或在线预览。

网上方案很多——有收费的 Aspose、有重量级的 LibreOffice,也有轻量的 docx4j
本文将介绍一个完全开源、部署简单、纯 Java 的实现方案:

使用 docx4j 在 Spring Boot 中实现 .docx → .pdf 转换。


一、方案选型对比

方案是否开源外部依赖样式保真度部署复杂度备注
Apache POI + iText对复杂格式支持差
docx4j⭐⭐推荐,纯 Java
LibreOffice + JODConverter需安装 LibreOffice很高⭐⭐⭐部署复杂
Aspose.Words最高收费,商业许可

选择理由

  • docx4j 是纯 Java 实现,无需安装 Office 或 LibreOffice;
  • 开源(Apache 2.0 License),免费可商用;
  • 转换质量好,能保留图片、表格、页眉页脚;
  • 容易集成进 Spring Boot。

二、添加 Maven 依赖

pom.xml 中加入以下依赖:

<dependencies><dependency><groupId>org.docx4j</groupId><artifactId>docx4j-core</artifactId><version>11.4.8</version></dependency><dependency><groupId>org.docx4j</groupId><artifactId>docx4j-JAXB-ReferenceImpl</artifactId><version>11.4.8</version></dependency><dependency><groupId>org.docx4j</groupId><artifactId>docx4j-export-fo</artifactId><version>11.4.8</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>2.0.9</version></dependency>
</dependencies>

三、核心工具类:DocxToPdfUtil

utils 包下创建 DocxToPdfUtil.java

package com.donglin.utils;
import org.docx4j.Docx4J;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFont;
import org.docx4j.fonts.PhysicalFonts;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import java.io.File;
import java.io.FileOutputStream;
public class DocxToPdfUtil {
/**
* 将 docx 文件转换为 PDF
*
* @param docxPath 输入文件路径
* @param pdfPath  输出文件路径
*/
public static void convert(String docxPath, String pdfPath) {
try {
// 1. 加载 Word 文档
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new File(docxPath));
// 2. 配置字体映射(防止中文乱码)
Mapper fontMapper = new IdentityPlusMapper();
PhysicalFonts.discoverPhysicalFonts();
PhysicalFont simsun = PhysicalFonts.get("SimSun");
if (simsun != null) {
fontMapper.put("SimSun", simsun);
// 常用中文字体映射表
fontMapper.put("隶书", PhysicalFonts.get("LiSu"));
fontMapper.put("宋体", PhysicalFonts.get("SimSun"));
fontMapper.put("微软雅黑", PhysicalFonts.get("Microsoft YaHei"));
fontMapper.put("黑体", PhysicalFonts.get("SimHei"));
fontMapper.put("楷体", PhysicalFonts.get("KaiTi"));
fontMapper.put("新宋体", PhysicalFonts.get("NSimSun"));
fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));
fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong"));
fontMapper.put("仿宋", PhysicalFonts.get("FangSong"));
fontMapper.put("幼圆", PhysicalFonts.get("YouYuan"));
fontMapper.put("华文宋体", PhysicalFonts.get("STSong"));
fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong"));
fontMapper.put("等线", PhysicalFonts.get("SimSun"));
fontMapper.put("等线 Light", PhysicalFonts.get("SimSun"));
fontMapper.put("华文琥珀", PhysicalFonts.get("STHupo"));
fontMapper.put("华文隶书", PhysicalFonts.get("STLiti"));
fontMapper.put("华文新魏", PhysicalFonts.get("STXinwei"));
fontMapper.put("华文彩云", PhysicalFonts.get("STCaiyun"));
fontMapper.put("方正姚体", PhysicalFonts.get("FZYaoti"));
fontMapper.put("方正舒体", PhysicalFonts.get("FZShuTi"));
fontMapper.put("华文细黑", PhysicalFonts.get("STXihei"));
fontMapper.put("宋体扩展", PhysicalFonts.get("simsun-extB"));
fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));
fontMapper.put("新細明體", PhysicalFonts.get("SimSun"));
// ⚙️ 修复 “宋体(正文)/宋体(标题)” 乱码
PhysicalFonts.put("PMingLiU", PhysicalFonts.get("SimSun"));
PhysicalFonts.put("新細明體", PhysicalFonts.get("SimSun"));
wordMLPackage.setFontMapper(fontMapper);
}
// 3. 创建输出流并执行转换
try (FileOutputStream os = new FileOutputStream(pdfPath)) {
Docx4J.toPDF(wordMLPackage, os);
}
System.out.println("✅ PDF 生成成功:" + pdfPath);
} catch (Exception e) {
System.err.println("❌ 转换失败:" + e.getMessage());
}
}
}

四、Controller 示例

controller 包中创建一个上传接口:

import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
@RestController
@RequestMapping("/convert")
public class FileController {
@GetMapping("/convertToPdf")
public void convertToPdf(@RequestParam String filePath, HttpServletResponse response) throws Exception {
// 1、 检查文件是否存在
File inputFile = new File(filePath);
if (!inputFile.exists()) {
throw new RuntimeException("文件不存在: " + filePath);
}
// 2、 定义输出路径(临时文件)
String pdfPath = filePath.replace(".docx", ".pdf");
// 3、 调用转换工具
DocxToPdfUtil.convert(filePath, pdfPath);
// 4、 设置响应头并输出 PDF 文件
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=" + new File(pdfPath).getName());
try (FileInputStream fis = new FileInputStream(pdfPath);
OutputStream os = response.getOutputStream()) {
fis.transferTo(os);
os.flush();
}
// 可选:删除临时 PDF 文件
new File(pdfPath).delete();
}
}

使用 Postman 发送请求:

GET http://localhost:8080/convertToPdf?filePath=filePath=E:/ai/report.docx

选择一个 .docx 文件上传,即可生成同名 .pdf 文件。


五、Windows解决中文乱码问题

在这里插入图片描述
增加字体的类别

fontMapper.put("SimSun", simsun);
// 常用中文字体映射表
fontMapper.put("隶书", PhysicalFonts.get("LiSu"));
fontMapper.put("宋体", PhysicalFonts.get("SimSun"));
fontMapper.put("微软雅黑", PhysicalFonts.get("Microsoft YaHei"));
fontMapper.put("黑体", PhysicalFonts.get("SimHei"));
fontMapper.put("楷体", PhysicalFonts.get("KaiTi"));
fontMapper.put("新宋体", PhysicalFonts.get("NSimSun"));
fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));
fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong"));
fontMapper.put("仿宋", PhysicalFonts.get("FangSong"));
fontMapper.put("幼圆", PhysicalFonts.get("YouYuan"));
fontMapper.put("华文宋体", PhysicalFonts.get("STSong"));
fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong"));
fontMapper.put("等线", PhysicalFonts.get("SimSun"));
fontMapper.put("等线 Light", PhysicalFonts.get("SimSun"));
fontMapper.put("华文琥珀", PhysicalFonts.get("STHupo"));
fontMapper.put("华文隶书", PhysicalFonts.get("STLiti"));
fontMapper.put("华文新魏", PhysicalFonts.get("STXinwei"));
fontMapper.put("华文彩云", PhysicalFonts.get("STCaiyun"));
fontMapper.put("方正姚体", PhysicalFonts.get("FZYaoti"));
fontMapper.put("方正舒体", PhysicalFonts.get("FZShuTi"));
fontMapper.put("华文细黑", PhysicalFonts.get("STXihei"));
fontMapper.put("宋体扩展", PhysicalFonts.get("simsun-extB"));
fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));
fontMapper.put("新細明體", PhysicalFonts.get("SimSun"));
// ⚙️ 修复 “宋体(正文)/宋体(标题)” 乱码
PhysicalFonts.put("PMingLiU", PhysicalFonts.get("SimSun"));
PhysicalFonts.put("新細明體", PhysicalFonts.get("SimSun"));
wordMLPackage.setFontMapper(fontMapper);

六、Linux解决中文乱码问题

在 Linux 环境中安装 Windows 字体

新建字体文件夹

sudo mkdir -p /usr/share/fonts/win_font

拷贝 Windows 字体文件

Windows 10 系统中路径为 C:\Windows\Fonts 的字体文件
拷贝到 Linux 的 /usr/share/fonts/win_font 目录中。

加载字体文件

进入字体目录并执行以下命令:

cd /usr/share/fonts/win_font
sudo mkfontscale       # 生成字体缩放文件
sudo mkfontdir         # 生成字体目录索引
sudo fc-cache -fv      # 刷新字体缓存

查看字体安装情况

执行以下命令查看中文字体是否成功加载:

fc-list :lang=zh

在这里插入图片描述

七、总结

  • 使用开源库 docx4j
  • 无需安装 Office 或 LibreOffice;
  • 保留常见样式、图片、表格;
  • 性能高、部署轻量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/969041.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【FAQ】HarmonyOS SDK 闭源开放能力 — Notification Kit

1.问题描述: 获取应用是否开启了允许通知权限后,如何引导跳转开启权限通知的设置页面? 解决方案:通过isNotificationEnabled方法查询通知是否授权,参考isNotificationEnabled用法。2.若申请通知权限被拒绝后,后续…

2025年中国试验机厂家推荐榜:十强排名与性能评测(山东万辰、盛林试验机领衔国产标杆)

2025年中国试验机厂家推荐榜:十强排名与性能评测(山东万辰、盛林试验机领衔国产标杆)在航空航天、机械制造、新能源、医疗设备、科研院校等领域,试验机作为材料力学性能检测的核心装备,直接决定产品质量与科研数据…

逻辑芯片 - 电子开关

逻辑芯片 - 电子开关ADG408、ADG409、ADG1408、ADG1409、ADG411、ADG1411、DG467系列和WAS3157BSTM32开发项目:一些模拟电子开关的介绍与驱动本文档详细介绍了ADG408、ADG409、ADG1408、ADG1409、ADG411、ADG1411、DG…

2025 最新压花辊源头厂家权威推荐榜:国际协会测评认证,覆盖多材质适用场景的品质厂商精选布料压花辊 / 木材压花辊 / 真皮压花辊 / 铝膜压花辊 / 珍珠棉压花辊 / 薄膜压花辊公司推荐

引言 在全球压花辊采购市场中,“源头直采” 已成为制造企业控制成本、保障产能的关键路径,但市场中资质参差不齐的供应商让采购决策充满挑战。为解决这一痛点,本次榜单依托国际压花设备行业协会(IAE)最新测评体系…

2025年铝爬架网厂家权威推荐:新型建筑爬架网/米字爬架网/外墙建筑爬架网源头厂家精选

随着中国建筑业迈向高质量发展新阶段,铝爬架网作为建筑施工安全防护的核心材料,正迎来产品升级与市场扩容的重要机遇期。 在建筑行业标准化、绿色化发展的推动下,铝爬架网市场呈现出稳定增长态势。作为建筑施工安全…

CPP 格式化文件 .clang-format

--- Language: Cpp # BasedOnStyle: ChromiumColumnLimit: 0 # 注释与代码不再受列数限制 ReflowComments: false # 禁止自动重新排版注释MaxEmptyLinesToKeep: 1 SeparateDefinitionBlocks: Always …

2025年智能化矿山模型沙盘实力厂家权威推荐榜单:煤矿地质模型/井下开采仿真模型/智能矿井模型源头厂家精选

中国智慧矿山市场规模预计在2025年将突破1000亿元,其中智能化矿山模型沙盘作为矿山数字化建设的重要展示工具,年需求量增长率稳定在20%以上。 智能化矿山模型沙盘通过三维可视化、动态仿真和物联网技术,为矿山企业提…

com.unitree.doggo2

This XML file does not appear to have any style information associated with it. The document tree is shown below. <manifest xmlns:android="http://schemas.android.com/apk/res/android" andro…

通过SSH转发端口

情景 存在一个Linux服务器,只开放22端口。通过ssh转发将服务转发到中转服务器。 命令 ssh -L 0.0.0.0:8888:localhost:80 liuyang@172.24.52.208 -p 22nohup sudo autossh -M 0 -o "ServerAliveInterval 30"…

Codeforces Round 1064题解

太摆了QWQ前言 当时非常不想打但还是打了,非常没有耐心,导致B题题目太长不想看,C题题目看错导致20分钟没了,然后就不想做了,于是现在补题,准备今晚的div3.如果我有耐心的话。 题目 A. Same Difference 只能前一个…

2025 最新工业检测仪源头厂家推荐排行榜:粉尘气体 / 颗粒物 / 固体流量等设备靠谱企业精选固体流量/空间环境粉尘/便携式粉尘检测仪公司推荐

引言 随着环保政策趋严与工业智能化升级,粉尘浓度、气体含量、固体流量等检测设备成为企业合规运营的核心保障。当前市场中,检测仪器品牌良莠不齐,部分厂家存在技术滞后、检测精度不足、售后缺失等问题,导致企业采…

CVPR 2024 目标检测!开放词汇

CVPR 2024 目标检测!开放词汇01 论文概述 论文名称:YOLO-World: Real-Time Open-Vocabulary Object Detection 会议名称:CVPR (2024) 👉一键直达论文 [👉Lab4AI大模型实验室论文](https://www.lab4ai.cn/pape…

国标GB28181算法算力平台EasyGBS如何实现停车场监控系统的高效统一管理?

在智慧城市建设进程中,城市机动车保有量激增,传统停车场管理面临设备管理复杂、安防事件响应滞后、运营效率低下等痛点。本文将深入解析,基于国标GB28181协议的国标GB28181算法算力平台EasyGBS,如何通过 “统一接入…

LiteFlow(规则引擎)

LiteFlow(规则引擎)简介LiteFlow是一款轻量级、组件式的规则引擎框架,支持业务逻辑的编排和热刷新,适用于复杂业务场景的组件化管理。有时间再写……

SCQL:安全协同查询平台的技术解析

SCQL:安全协同查询平台的技术深度解析 在当今数据驱动的时代,跨机构数据协同分析需求日益增长,但数据隐私和合规要求(如GDPR)导致了数据孤岛问题。Secure Multi-Party Computation(MPC)技术为实现安全协同分析提…

linux apache 解析php

在 Linux 系统中,Apache 服务器默认使用 mod_php 模块来解析 .php 文件。以下是一些关于 Apache 解析 PHP 的常见命令和配置方法:一、确认 Apache 是否支持 PHP apache2ctl -t 如果输出中包含 mod_php,说明 Apache …

linux apache 的日志

在 Linux 系统中,Apache 服务器的日志通常位于以下路径: 1. Apache 2 的日志目录错误日志:/var/log/httpd/error_log(对于 Apache 2) 访问日志:/var/log/httpd/access_log(对于 Apache 2)2. Apache 2.4 的日志…

idea中maven转gradle

一、下载gradle包并解压 https://services.gradle.org/distributions/gradle-8.10-bin.zip 二、配置环境变量open -e ~/.zshrcexport GRADLE_HOME=/Users/edy/usr/local/gradle-8.10 export PATH=$GRADLE_HOME/bin:$PA…

linux apache 版本

要查看 Linux 系统中 Apache 服务器的版本,可以使用以下几种常用命令: 方法 1:使用 apache2 -v(适用于 Debian/Ubuntu)或 httpd -v(适用于 CentOS/RHEL) # Debian/Ubuntu apache2 -v# CentOS/RHEL httpd -v 方法…

从0死磕全栈之Next.js 本地开发环境优化最佳实践 - 指南

从0死磕全栈之Next.js 本地开发环境优化最佳实践 - 指南2025-11-18 15:31 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; …