Convert Word (.docx) to PDF in Spring Boot with docx4j – A Complete Guide
Learn how to convert user‑uploaded .docx files to PDF in a Spring Boot application using the pure‑Java docx4j library, covering solution comparison, Maven dependencies, utility class implementation, controller endpoint, and handling Chinese font issues on Windows and Linux.
Background
In many projects users need to upload Word (.docx) files and obtain PDF versions for download, archiving, or online preview.
Solution Comparison
Apache POI + iText – open source, no external dependencies, medium style fidelity, low deployment complexity, poor support for complex formats.
docx4j – open source, no external dependencies, high style fidelity, moderate deployment complexity, recommended for pure Java projects.
LibreOffice + JODConverter – open source, requires LibreOffice installation, very high style fidelity, high deployment complexity.
Aspose.Words – commercial, no external dependencies, highest style fidelity, low deployment complexity but requires a paid license.
Why Choose docx4j
Pure Java implementation, no need to install Office or LibreOffice.
Apache 2.0 license, free for commercial use.
Good conversion quality, retains images, tables, headers and footers.
Easy to integrate into Spring Boot.
Add Maven Dependencies
<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>Utility Class: DocxToPdfUtil
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 {
/**
* Convert a docx file to PDF.
* @param docxPath input file path
* @param pdfPath output file path
*/
public static void convert(String docxPath, String pdfPath) {
try {
// 1. Load the Word document
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new File(docxPath));
// 2. Configure font mapper to avoid Chinese garbled text
Mapper fontMapper = new IdentityPlusMapper();
PhysicalFonts.discoverPhysicalFonts();
PhysicalFont simsun = PhysicalFonts.get("SimSun");
if (simsun != null) {
fontMapper.put("SimSun", simsun);
// Common Chinese font mappings
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"));
// Fix "SimSun" garbled text for certain styles
PhysicalFonts.put("PMingLiU", PhysicalFonts.get("SimSun"));
PhysicalFonts.put("新細明體", PhysicalFonts.get("SimSun"));
wordMLPackage.setFontMapper(fontMapper);
}
// 3. Create output stream and perform conversion
try (FileOutputStream os = new FileOutputStream(pdfPath)) {
Docx4J.toPDF(wordMLPackage, os);
}
System.out.println("✅ PDF generated successfully: " + pdfPath);
} catch (Exception e) {
System.err.println("❌ Conversion failed: " + e.getMessage());
}
}
}Controller Example
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/convert")
public class FileController {
@GetMapping("/convertToPdf")
public void convertToPdf(@RequestParam String filePath, HttpServletResponse response) throws Exception {
// 1. Verify file existence
File inputFile = new File(filePath);
if (!inputFile.exists()) {
throw new RuntimeException("File not found: " + filePath);
}
// 2. Define temporary PDF output path
String pdfPath = filePath.replace(".docx", ".pdf");
// 3. Call conversion utility
DocxToPdfUtil.convert(filePath, pdfPath);
// 4. Set response headers and stream PDF back to client
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();
}
// Optional: delete temporary PDF file
new File(pdfPath).delete();
}
}Testing with Postman
Send a GET request such as:
GET http://localhost:8080/convertToPdf?filePath=E:/ai/report.docxUpload a .docx file and the service returns a PDF with the same name.
Fixing Chinese Font Issues on Windows
The utility class configures a comprehensive font mapper that maps many Chinese fonts (SimSun, LiSu, KaiTi, etc.) to avoid garbled characters when converting on Windows.
Fixing Chinese Font Issues on Linux
Install Windows fonts on the Linux server and refresh the font cache:
sudo mkdir -p /usr/share/fonts/win_font
cd /usr/share/fonts/win_font
sudo mkfontscale # generate font scale file
sudo mkfontdir # generate font directory index
sudo fc-cache -fv # refresh font cacheVerify the installation with:
fc-list :lang=zhConclusion
Use the open‑source docx4j library.
No need to install Office or LibreOffice.
Preserves common styles, images, and tables.
High performance and lightweight deployment.
Java Tech Enthusiast
Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
