当前位置: 首页 > news >正文

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

目录

  • 一、方案选型对比
  • 二、添加 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.dtcms.com/a/520143.html

相关文章:

  • 服装企业官方网站建设网站运营收入
  • Spring Boot Actuator深度解析与实战
  • 如何做 行业社交类网站网站 建设在作用
  • 线程3 JavaEE(阻塞队列,线程池)
  • K8s中,deployment 是如何从 yaml 文件最终部署成功 pod 的
  • RK3588 使用 FFmpeg 硬件解码输出到 DRM Prime (DMA Buf) 加速数据传输
  • 基于蚁群算法的PID参数整定方法及MATLAB实现
  • 排序算法大全——插入排序
  • 手搓一个CUDA JIT编译器
  • 网站引导页模板互联网公司排名全球
  • JDK 9 List.of(...)
  • 做一个vue3 v-model 双向绑定的弹窗
  • 为超过10亿条记录的订单表新增字段
  • 哪里做网站最便宜WordPress功能模块排版
  • 每日算法刷题Day78:10.23:leetcode 一般树7道题,用时1h30min
  • 薄膜测厚选CWL法还是触针法?针对不同厚度与材质的台阶仪技术选型指南
  • WPF-MVVM的简单入门(第一个MVVM程序)
  • blender拓扑建模教程
  • asp.net手机网站开发教程翻译网站建设方案
  • 佛山建设网站公司哪家好特斯拉ceo进厂拧螺丝
  • 如何做新网站保留域名wordpress基础
  • C# 实现 Modbus TCP 通信
  • 《Git:从入门到精通(七)——Git分支管理与协作开发实战》
  • 超越传统工具:利用Reddit发现关键词的独特视角与前沿方法
  • 数据结构——二叉搜索树深度解析
  • macOS 无法在根目录创建目录的原因与解决方案
  • 11.23 鸿蒙HTTP数据请求
  • 郑州网站建设最低价网址导航的意思
  • LOESS回归
  • 跨平台开发中的图形渲染:Canvas与View+CSS的性能分析与决策路径