Java高效實(shí)現(xiàn)Word轉(zhuǎn)PDF的完整指南
Java開發(fā)中如何高效穩(wěn)定地將Word文檔轉(zhuǎn)換為PDF格式? 這個(gè)看似簡(jiǎn)單的需求,在企業(yè)合同電子歸檔、財(cái)務(wù)報(bào)表批量生成等場(chǎng)景中,開發(fā)者往往會(huì)遇到不同的問(wèn)題,如樣式錯(cuò)亂、字體丟失等。
今天我們將通過(guò)實(shí)測(cè)代碼,展示如何用 Spire.Doc for Java 庫(kù)實(shí)現(xiàn)Word到PDF文檔的快速轉(zhuǎn)換,并解析其轉(zhuǎn)換選項(xiàng)的靈活配置技巧。
方法一:三步實(shí)現(xiàn)核心功能
步驟1:添加Maven依賴
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.xls</artifactId>
<version>15.7.7</version>
</dependency>
</dependencies>
步驟2:核心代碼示例 (支持Doc和Docx格式)
// 創(chuàng)建文檔對(duì)象模型
Document doc = new Document();
// 加載Word
doc.loadFromFile("input.docx");
// 保存為PDF
doc.saveToFile("output.pdf", FileFormat.PDF);
doc.dispose();
步驟3:異常處理
try {
// 轉(zhuǎn)換代碼...
} catch (DocumentException e) {
System.err.println("轉(zhuǎn)換失敗: " + e.getMessage());
throw new RuntimeException(e);
}
最佳實(shí)踐
生產(chǎn)環(huán)境務(wù)必調(diào)用doc.close()釋放資源,避免服務(wù)器出現(xiàn)文件句柄泄露
方法二:高級(jí)選項(xiàng)配置
轉(zhuǎn)換過(guò)程中通過(guò) ToPdfParameterList 對(duì)象可實(shí)現(xiàn)精細(xì)控制:
| 選項(xiàng)參數(shù) | 作用描述 | 典型應(yīng)用場(chǎng)景 |
|---|---|---|
| isEmbeddedAllFonts | 強(qiáng)制嵌入所有字體 | 跨系統(tǒng)排版一致性 |
| setDisableLink | 禁用超鏈接 | 安全文檔轉(zhuǎn)換 |
| setPdfConformanceLevel | 設(shè)置PDF標(biāo)準(zhǔn)規(guī)范 | 歸檔級(jí)文檔(法律/醫(yī)療 |
| setCreateWordBookmarks | 保留書簽 | 技術(shù)手冊(cè)/論文等長(zhǎng)文檔導(dǎo)航 |
加密PDF代碼示例:
// 高級(jí)轉(zhuǎn)換配置示例
ToPdfParameterList options = new ToPdfParameterList();
options.setPdfConformanceLevel(PdfConformanceLevel.Pdf_A_1_B); // 符合PDF/A-1b標(biāo)準(zhǔn)
String password1 = "E-iceblue"; // 打開密碼
String password2 = "123"; // 用戶密碼
options..getPdfSecurity().encrypt(password1, password2, PdfPermissionsFlags.None, PdfEncryptionKeySize.Key_128_Bit); // 加密PDF
// 轉(zhuǎn)換Word為PDF
Document doc = new Document();
doc.loadFromFile("機(jī)密報(bào)告.docx");
doc.saveToFile("加密文檔.pdf", options);
最佳實(shí)踐
轉(zhuǎn)換時(shí)還可通過(guò) setJPEGQuality 設(shè)置圖片壓縮質(zhì)量 (0-100),以優(yōu)化PDF體積。
性能優(yōu)化建議
內(nèi)存管理: 處理50頁(yè)以上文檔時(shí),采用分段加載減少單次內(nèi)存占用
批量處理:
File[] files = new File("docs/").listFiles((dir, name) -> name.endsWith(".docx"));
for (File file : files) {
// 循環(huán)調(diào)用轉(zhuǎn)換方法...
}
方法補(bǔ)充
Java 實(shí)現(xiàn) Word 轉(zhuǎn)PDF方案
轉(zhuǎn)換方案選擇
項(xiàng)目開發(fā)我主要使用過(guò) Aspose 和 LibreOffice,兩者代碼實(shí)現(xiàn)都很簡(jiǎn)單,轉(zhuǎn)換效果也不錯(cuò)。其他生成 pdf 的方案,比如使用 html 轉(zhuǎn)換、xml、或者直接操作 pdf 模板,實(shí)際使用代碼邏輯繁瑣不易理解,且轉(zhuǎn)換生成效果一般。LibreOffice主要是后期做復(fù)雜的 pdf 模板導(dǎo)出,使用 word 難以動(dòng)態(tài)填充內(nèi)容,后來(lái)使用 excel,在 java中計(jì)算后填充 excel,設(shè)置好格式在轉(zhuǎn)換拼接 pdf 最后輸出。
- Aspose:商業(yè)收費(fèi)軟件,免費(fèi)版有水印。
- LibreOffice:開源免費(fèi), 需要部署環(huán)境安裝LibreOffice,實(shí)際使用需要控制并發(fā)與文件大小,避免對(duì)服務(wù)器整體造成影響。
Aspose 實(shí)現(xiàn)方案
a. 依賴注入
可以直接下載 jar 包,注入 maven 依賴后直接使用:
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>15.8.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/aspose-words-15.8.0-jdk16.jar</systemPath>
</dependency>
b. 實(shí)際使用
基本用法:
// 先創(chuàng)建一個(gè)臨時(shí)文件用來(lái)存儲(chǔ) PDF
String pdfPath = FileUtils.getTempDirectoryPath() + System.currentTimeMillis() + ".pdf";
/**
* 加載license 用于破解 不生成水印
*/
@SneakyThrows
private static void getLicense() {
try (InputStream is = AsposeUtil.class.getClassLoader().getResourceAsStream("lib/License.xml")) {
License license = new License();
license.setLicense(is);
}
}
/**
* word轉(zhuǎn)pdf
*
* @param wordPath word文件保存的路徑
* @param pdfPath 轉(zhuǎn)換后pdf文件保存的路徑
*/
public static void wordToPdf(String wordPath, String pdfPath) throws Exception {
// 獲取許可證
getLicense();
// 加載 Word 文檔
Document doc = new Document(wordPath);
// 設(shè)置 PdfSaveOptions
PdfSaveOptions options = new PdfSaveOptions();
options.setSaveFormat(SaveFormat.PDF);
// 保存為 PDF
try (FileOutputStream os = new FileOutputStream(pdfPath)) {
doc.save(os, options);
}
}
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Words for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
</Data>
<Signature> sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=
</Signature>
</License>
c. 常見問(wèn)題與解決思路
1. 字體文件缺失導(dǎo)致轉(zhuǎn)換亂碼
場(chǎng)景:在服務(wù)器或 Docker 環(huán)境下運(yùn)行,可能會(huì)因缺少字體導(dǎo)致 PDF 亂碼。
解決方案一:將字體文件放在服務(wù)器的字體目錄,Docker 可在啟動(dòng)時(shí)拷貝字體。
# 使用帶完整字體庫(kù)的基礎(chǔ)鏡像 FROM openjdk:17-jdk-slim # 拷貝字體 COPY fonts/ /usr/share/fonts/truetype/custom/ # 刷新字體緩存 RUN fc-cache -fv
解決方案二:將字體文件放在項(xiàng)目的 resources/fonts 目錄下,導(dǎo)出時(shí)拷貝到臨時(shí)目錄后再進(jìn)行轉(zhuǎn)換(只需轉(zhuǎn)換一次)。
private final static String[] FONT_PATHS = {"fonts/Songti.ttc"};
fontPath = copyTempFileFont(FONT_PATHS);
/**
* 將項(xiàng)目中的字體文件拷貝到臨時(shí)目錄
* @return 字體目錄路徑
*/
private static String copyTempFileFont(String... fontPath) {
String tempDir = System.getProperty("java.io.tmpdir");
File fontDir = new File(tempDir, "fonts");
if (!fontDir.exists()) {
fontDir.mkdirs(); // 創(chuàng)建目錄
}
for (String path : fontPath) {
File tempFile = new File(fontDir, new File(path).getName());
if (!tempFile.exists()) {
try (InputStream inputStream = Object.class.getClassLoader().getResourceAsStream(path)) {
FileUtils.copyInputStreamToFile(inputStream, tempFile);
} catch (IOException e) {
throw new RuntimeException("字體文件轉(zhuǎn)換失敗,請(qǐng)稍候重試");
}
}
}
return fontDir.getPath() + "/";
}
帶字體目錄的轉(zhuǎn)換方法:
/**
* word轉(zhuǎn)pdf(指定字體目錄)
*
* @param wordPath word文件保存的路徑
* @param pdfPath 轉(zhuǎn)換后pdf文件保存的路徑
* @param fontPath 字體目錄
*/
public static void wordToPdf(String wordPath, String pdfPath, String fontPath) throws Exception {
// 獲取許可證
getLicense();
// 設(shè)置字體文件夾
FontSettings.setFontsFolder(fontPath, false);
// 加載 Word 文檔
Document doc = new Document(wordPath);
// 設(shè)置 PdfSaveOptions
PdfSaveOptions options = new PdfSaveOptions();
options.setSaveFormat(SaveFormat.PDF);
// 保存為 PDF
try (FileOutputStream os = new FileOutputStream(new File(pdfPath))) {
doc.save(os, options);
}
}LibreOffice 實(shí)現(xiàn)方案(對(duì)應(yīng) excel 也可以直接使用)
a. JODConverter(調(diào)用 LibreOffice 轉(zhuǎn)換)
引入依賴
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-local</artifactId>
<version>4.4.4</version>
</dependency>
代碼實(shí)現(xiàn)
/**
* 轉(zhuǎn)換為PDF(同時(shí)適用于 word excel)
* @param file
* @return
* @throws OfficeException
* @throws IOException
*/
public File convertToPdf(File file) throws OfficeException, IOException {
File tempPdfFile = File.createTempFile(String.valueOf(System.currentTimeMillis()), ".pdf");
LocalOfficeManager officeManager = null;
try {
officeManager = (LocalOfficeManager.builder().install()).build();
officeManager.start();
(LocalConverter.builder().officeManager(officeManager)).build().convert(file).to(tempPdfFile).execute();
} finally {
if (officeManager != null) {
officeManager.stop();
}
}
return tempPdfFile;
}拼接pdf
a. 依賴
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.1.15</version>
</dependency>
b. 實(shí)現(xiàn)
/**
* 合并PDF文件
*/
private void mergePdfFiles(List<File> pdfFiles, String outputPath) throws IOException {
try (PdfWriter writer = new PdfWriter(outputPath);
PdfDocument mergedDoc = new PdfDocument(writer)) {
PdfMerger merger = new PdfMerger(mergedDoc);
for (File pdfFile : pdfFiles) {
try (PdfReader reader = new PdfReader(pdfFile);
PdfDocument sourceDoc = new PdfDocument(reader)) {
merger.merge(sourceDoc, 1, sourceDoc.getNumberOfPages());
}
}
}
}到此這篇關(guān)于Java高效實(shí)現(xiàn)Word轉(zhuǎn)PDF的完整指南的文章就介紹到這了,更多相關(guān)Java Word轉(zhuǎn)PDF內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot返回圖片流的實(shí)現(xiàn)示例
本文主要介紹了springboot返回圖片流的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
springboot+thymeleaf找不到視圖的解決方案
這篇文章主要介紹了springboot+thymeleaf找不到視圖的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Java局部?jī)?nèi)部類和匿名內(nèi)部類定義與用法實(shí)例分析
這篇文章主要介紹了Java局部?jī)?nèi)部類和匿名內(nèi)部類,結(jié)合實(shí)例形式分析了java局部?jī)?nèi)部類和匿名內(nèi)部類相關(guān)定義、原理與用法,需要的朋友可以參考下2019-08-08
如何通過(guò)JVM角度談?wù)凧ava的clone操作
java中僅有的創(chuàng)建對(duì)象的兩種方式:①.使用new操作符創(chuàng)建對(duì)象;②.使用clone方法復(fù)制對(duì)象。下面這篇文章主要通過(guò)JVM角度給大家詳細(xì)談?wù)凧ava的clone操作的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-06-06
Java中l(wèi)og4j注解詳解與實(shí)戰(zhàn)指南(附具體示例)
日志是軟件開發(fā)中不可或缺的一部分,它能夠幫助開發(fā)者追蹤程序的運(yùn)行狀態(tài),診斷問(wèn)題,以及監(jiān)控系統(tǒng)性能,這篇文章主要介紹了Java中l(wèi)og4j注解詳解與實(shí)戰(zhàn)的相關(guān)資料,需要的朋友可以參考下2025-07-07
Spring Boot3整合Mybatis Plus的詳細(xì)過(guò)程(數(shù)據(jù)庫(kù)為MySQL)
這篇文章主要介紹了Spring Boot3整合Mybatis Plus的詳細(xì)過(guò)程(數(shù)據(jù)庫(kù)為MySQL),本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-07-07
Spring實(shí)現(xiàn)Bean的初始化和銷毀的方式
這篇文章主要介紹了Spring實(shí)現(xiàn)Bean的初始化和銷毀的方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-05-05
Java實(shí)現(xiàn)利用圖片或視頻生成GIF并發(fā)送微信
這篇文章主要為大家詳細(xì)介紹了Java語(yǔ)言如何利用圖片或視頻實(shí)現(xiàn)生成GIF并發(fā)送微信的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下2022-11-11

