最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot基于docx4j實(shí)現(xiàn)DOCX轉(zhuǎn)PDF的具體方案

 更新時(shí)間:2025年11月09日 13:45:59   作者:Knight_AL  
在日常項(xiàng)目開(kāi)發(fā)中,我們經(jīng)常遇到用戶上傳 Word( .docx)文件,希望后臺(tái)自動(dòng)生成 PDF,用于下載、歸檔或在線預(yù)覽,本文將介紹一個(gè)完全開(kāi)源、部署簡(jiǎn)單、純 Java 的實(shí)現(xiàn)方案,感興趣的小伙伴可以跟著小編一起來(lái)看看

在日常項(xiàng)目開(kāi)發(fā)中,我們經(jīng)常遇到這樣的需求:
用戶上傳 Word( .docx)文件,希望后臺(tái)自動(dòng)生成 PDF,用于下載、歸檔或在線預(yù)覽。
網(wǎng)上方案很多——有收費(fèi)的 Aspose、有重量級(jí)的 LibreOffice,也有輕量的 docx4j。

本文將介紹一個(gè)完全開(kāi)源、部署簡(jiǎn)單、純 Java 的實(shí)現(xiàn)方案:使用 docx4j 在 Spring Boot 中實(shí)現(xiàn) .docx → .pdf 轉(zhuǎn)換。

一、方案選型對(duì)比

方案是否開(kāi)源外部依賴(lài)樣式保真度部署復(fù)雜度備注
Apache POI + iText?無(wú)?對(duì)復(fù)雜格式支持差
docx4j?無(wú)??推薦,純 Java
LibreOffice + JODConverter?需安裝 LibreOffice很高???部署復(fù)雜
Aspose.Words?無(wú)最高?收費(fèi),商業(yè)許可

選擇理由

  • docx4j 是純 Java 實(shí)現(xiàn),無(wú)需安裝 Office 或 LibreOffice;
  • 開(kāi)源(Apache 2.0 License),免費(fèi)可商用;
  • 轉(zhuǎn)換質(zhì)量好,能保留圖片、表格、頁(yè)眉頁(yè)腳;
  • 容易集成進(jìn) Spring Boot。

二、添加 Maven 依賴(lài)

在 pom.xml 中加入以下依賴(lài):

<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>

三、核心工具類(lèi):DocxToPdfUtil

在 utils 包下創(chuàng)建 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 文件轉(zhuǎn)換為 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("隸書(shū)", 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("華文隸書(shū)", 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("華文細(xì)黑", PhysicalFonts.get("STXihei"));
                fontMapper.put("宋體擴(kuò)展", PhysicalFonts.get("simsun-extB"));
                fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));
                fontMapper.put("新細(xì)明體", PhysicalFonts.get("SimSun"));

                // ?? 修復(fù) “宋體(正文)/宋體(標(biāo)題)” 亂碼
                PhysicalFonts.put("PMingLiU", PhysicalFonts.get("SimSun"));
                PhysicalFonts.put("新細(xì)明體", PhysicalFonts.get("SimSun"));
                wordMLPackage.setFontMapper(fontMapper);
            }

            // 3. 創(chuàng)建輸出流并執(zhí)行轉(zhuǎn)換
            try (FileOutputStream os = new FileOutputStream(pdfPath)) {
                Docx4J.toPDF(wordMLPackage, os);
            }

            System.out.println("? PDF 生成成功:" + pdfPath);
        } catch (Exception e) {
            System.err.println("? 轉(zhuǎn)換失敗:" + e.getMessage());
        }
    }
}

四、Controller 示例

在 controller 包中創(chuàng)建一個(gè)上傳接口:

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、 定義輸出路徑(臨時(shí)文件)
        String pdfPath = filePath.replace(".docx", ".pdf");

        // 3、 調(diào)用轉(zhuǎn)換工具
        DocxToPdfUtil.convert(filePath, pdfPath);

        // 4、 設(shè)置響應(yīng)頭并輸出 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();
        }

        // 可選:刪除臨時(shí) PDF 文件
        new File(pdfPath).delete();
    }
}

使用 Postman 發(fā)送請(qǐng)求:

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

選擇一個(gè) .docx 文件上傳,即可生成同名 .pdf 文件。

五、Windows解決中文亂碼問(wèn)題

增加字體的類(lèi)別

                fontMapper.put("SimSun", simsun);
                // 常用中文字體映射表
                fontMapper.put("隸書(shū)", 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("華文隸書(shū)", 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("華文細(xì)黑", PhysicalFonts.get("STXihei"));
                fontMapper.put("宋體擴(kuò)展", PhysicalFonts.get("simsun-extB"));
                fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));
                fontMapper.put("新細(xì)明體", PhysicalFonts.get("SimSun"));

                // ?? 修復(fù) “宋體(正文)/宋體(標(biāo)題)” 亂碼
                PhysicalFonts.put("PMingLiU", PhysicalFonts.get("SimSun"));
                PhysicalFonts.put("新細(xì)明體", PhysicalFonts.get("SimSun"));
                wordMLPackage.setFontMapper(fontMapper);

六、Linux解決中文亂碼問(wèn)題

在 Linux 環(huán)境中安裝 Windows 字體

新建字體文件夾

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

拷貝 Windows 字體文件

將 Windows 10 系統(tǒng)中路徑為 C:\Windows\Fonts 的字體文件
拷貝到 Linux 的 /usr/share/fonts/win_font 目錄中。

加載字體文件

進(jìn)入字體目錄并執(zhí)行以下命令:

cd /usr/share/fonts/win_font
sudo mkfontscale       # 生成字體縮放文件
sudo mkfontdir         # 生成字體目錄索引
sudo fc-cache -fv      # 刷新字體緩存

查看字體安裝情況

執(zhí)行以下命令查看中文字體是否成功加載:

fc-list :lang=zh

七、總結(jié)

  • 使用開(kāi)源庫(kù) docx4j
  • 無(wú)需安裝 Office 或 LibreOffice;
  • 保留常見(jiàn)樣式、圖片、表格;
  • 性能高、部署輕量。

以上就是SpringBoot基于docx4j實(shí)現(xiàn)DOCX轉(zhuǎn)PDF的具體方案的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot DOCX轉(zhuǎn)PDF的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 關(guān)于SpringBoot單元測(cè)試(cobertura生成覆蓋率報(bào)告)

    關(guān)于SpringBoot單元測(cè)試(cobertura生成覆蓋率報(bào)告)

    這篇文章主要介紹了關(guān)于SpringBoot單元測(cè)試(cobertura生成覆蓋率報(bào)告),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Springboot接收文件與發(fā)送文件實(shí)例教程

    Springboot接收文件與發(fā)送文件實(shí)例教程

    最近工作中遇到個(gè)需求,springboot簡(jiǎn)單的上傳文檔或者圖片,并且進(jìn)行操作,操作完后進(jìn)行保存指定路徑,下面這篇文章主要給大家介紹了關(guān)于Springboot接收文件與發(fā)送文件的相關(guān)資料,需要的朋友可以參考下
    2023-05-05
  • 深入解析SpringBatch適配器

    深入解析SpringBatch適配器

    Spring Batch是Spring的一個(gè)子項(xiàng)目,使用Java語(yǔ)言并基于Spring框架為基礎(chǔ)開(kāi)發(fā),使得已經(jīng)使用 Spring 框架的開(kāi)發(fā)者或者企業(yè)更容易訪問(wèn)和利用企業(yè)服務(wù),本文給大家介紹SpringBatch適配器的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-11-11
  • JVM與操作系統(tǒng)之間的關(guān)系詳解

    JVM與操作系統(tǒng)之間的關(guān)系詳解

    JVM與操作系統(tǒng)之間是依賴(lài)與被依賴(lài)的關(guān)系,JVM依賴(lài)于操作系統(tǒng)提供的資源和服務(wù),同時(shí)JVM也起到了抽象與隔離的作用,為Java程序提供了一個(gè)統(tǒng)一的、與平臺(tái)無(wú)關(guān)的運(yùn)行環(huán)境,提高了Java程序的安全性
    2025-03-03
  • 跟我學(xué)Java Swing之游戲設(shè)計(jì)(1)

    跟我學(xué)Java Swing之游戲設(shè)計(jì)(1)

    跟我學(xué)Java Swing之游戲設(shè)計(jì)(1)...
    2006-12-12
  • springboot網(wǎng)站應(yīng)用使用第三方qq登錄的實(shí)現(xiàn)過(guò)程

    springboot網(wǎng)站應(yīng)用使用第三方qq登錄的實(shí)現(xiàn)過(guò)程

    這篇文章主要介紹了springboot網(wǎng)站應(yīng)用使用第三方qq登錄,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • Java異常鏈表throw結(jié)構(gòu)assert詳細(xì)解讀

    Java異常鏈表throw結(jié)構(gòu)assert詳細(xì)解讀

    這篇文章主要給大家介紹了關(guān)于Java中方法使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • Java中鍵盤(pán)輸入的幾種常見(jiàn)方式小結(jié)

    Java中鍵盤(pán)輸入的幾種常見(jiàn)方式小結(jié)

    本文主要介紹了Java中鍵盤(pán)輸入的幾種常見(jiàn)方式小結(jié),主要是三種方式IO流、Scanner類(lèi)、BufferedReader寫(xiě)入,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • SpringBoot結(jié)合HTMX實(shí)現(xiàn)高效Web開(kāi)發(fā)實(shí)戰(zhàn)

    SpringBoot結(jié)合HTMX實(shí)現(xiàn)高效Web開(kāi)發(fā)實(shí)戰(zhàn)

    在當(dāng)今的 Web 開(kāi)發(fā)領(lǐng)域,前后端分離已成為主流趨勢(shì),本文將介紹一種輕量級(jí)的解決方案,結(jié)合 Spring Boot 與 HTMX,實(shí)現(xiàn)高效簡(jiǎn)潔的前后端分離開(kāi)發(fā),感興趣的可以了解下
    2025-07-07
  • Java中的線程池如何實(shí)現(xiàn)線程復(fù)用

    Java中的線程池如何實(shí)現(xiàn)線程復(fù)用

    這篇文章主要介紹了Java中的線程池如何實(shí)現(xiàn)線程復(fù)用問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03

最新評(píng)論

昭苏县| 扎兰屯市| 奇台县| 琼结县| 墨玉县| 龙游县| 交城县| 诸城市| 昌都县| 桐庐县| 临夏市| 开原市| 来安县| 大余县| 白朗县| 临漳县| 昌黎县| 道真| 洛阳市| 虞城县| 永善县| 新竹市| 农安县| 江西省| 五指山市| 焉耆| 曲麻莱县| 辽宁省| 隆尧县| 武山县| 平顺县| 徐水县| 石棉县| 五常市| 宾阳县| 万源市| 扎赉特旗| 沙雅县| 栖霞市| 江达县| 新沂市|