Java實現(xiàn)將Word和PDF轉(zhuǎn)成一張垂直拼接長圖的工具類
更新時間:2025年10月15日 08:54:11 作者:Uluoyu
這篇文章主要為大家詳細介紹了如何使用Java編寫一個將Word和PDF轉(zhuǎn)成一張垂直拼接長圖的工具類,支持doc和docx,有需要的小伙伴可以了解下
1.添加依賴
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version> <!-- 如果有 DOCX 相關(guān) -->
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>3.0.5</version>
</dependency>
<!-- Word轉(zhuǎn)PDF:Docx4J核心 -->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-JAXB-ReferenceImpl</artifactId>
<version>8.3.10</version>
</dependency>
<!-- Word轉(zhuǎn)PDF:FO導(dǎo)出支持(用于PDF渲染) -->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-export-fo</artifactId>
<version>8.3.10</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.3</version>
</dependency>
<!-- 如果 Docx4J 版本舊,還可能需激活模塊 -->
<dependency>
<groupId>com.sun.activation</groupId>
<artifactId>javax.activation</artifactId>
<version>1.2.0</version>
</dependency>
2.Java代碼
import lombok.extern.slf4j.Slf4j;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.io.RandomAccessReadBuffer;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.WordToFoConverter;
import org.docx4j.Docx4J;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.w3c.dom.Document;
import javax.imageio.ImageIO;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @Description 文檔轉(zhuǎn)長圖片工具類
* 支持Word (doc/docx) 和 PDF 轉(zhuǎn)成一張垂直拼接的長PNG圖片
*/
@Slf4j
public class DocumentToImageUtil {
/**
* 將文檔(Word或PDF)轉(zhuǎn)換為長圖片字節(jié)數(shù)組
* @param content 文檔字節(jié)數(shù)組
* @param fileType 文件類型(doc, docx, pdf)
* @return PNG圖片字節(jié)數(shù)組
* @throws IOException 轉(zhuǎn)換失敗
*/
public byte[] convertToStitchedImage(byte[] content, String fileType) throws IOException {
byte[] pdfContent = content;
if (fileType.toLowerCase().contains("doc") || fileType.toLowerCase().contains("docx")) {
pdfContent = convertWordToPdf(content, fileType.toLowerCase());
}
return convertPdfToStitchedImage(pdfContent);
}
/**
* Word轉(zhuǎn)PDF(支持doc和docx)
*/
private byte[] convertWordToPdf(byte[] wordContent, String fileType) throws IOException {
if (fileType.toLowerCase().contains("docx")) {
// DOCX轉(zhuǎn)PDF使用Docx4J
try (ByteArrayInputStream bais = new ByteArrayInputStream(wordContent)) {
WordprocessingMLPackage loadedPackage = WordprocessingMLPackage.load(bais);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Docx4J.toPDF(loadedPackage, baos);
return baos.toByteArray();
} catch (Exception e) {
throw new IOException("DOCX轉(zhuǎn)PDF失敗", e);
}
} else if (fileType.toLowerCase().contains("doc")) {
// DOC轉(zhuǎn)PDF使用POI HWPF + Transformer + FOP
try (ByteArrayInputStream bais = new ByteArrayInputStream(wordContent);
HWPFDocument document = new HWPFDocument(bais)) {
// 1. 使用 WordToFoConverter 生成 FO Document(移除 setFontResolver,使用默認)
Document foDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
WordToFoConverter converter = new WordToFoConverter(foDoc);
// 注意:在 POI 5.2.5 中,setFontResolver 已棄用或移除,使用默認字體解析器
converter.processDocument(document);
// 2. Transformer 將 FO Document 序列化為字節(jié)流
ByteArrayOutputStream foBaos = new ByteArrayOutputStream();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty(OutputKeys.METHOD, "xml"); // 輸出 XML-FO
serializer.transform(new DOMSource(foDoc), new StreamResult(foBaos));
byte[] foBytes = foBaos.toByteArray();
// 3. FOP 將 FO 轉(zhuǎn) PDF(使用帶URI參數(shù)的newInstance,避免解析問題)
FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI()); // 標準方式,設(shè)置base URI
ByteArrayOutputStream pdfBaos = new ByteArrayOutputStream();
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, pdfBaos);
Transformer transformer = tf.newTransformer(); // 身份轉(zhuǎn)換器
Source src = new StreamSource(new ByteArrayInputStream(foBytes));
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
return pdfBaos.toByteArray();
} catch (Exception e) {
throw new IOException("DOC轉(zhuǎn)PDF失敗", e);
}
} else {
throw new IOException("不支持的文件類型: " + fileType);
}
}
/**
* PDF轉(zhuǎn)垂直拼接的長圖片
*/
private byte[] convertPdfToStitchedImage(byte[] pdfContent) throws IOException {
try (ByteArrayInputStream bais = new ByteArrayInputStream(pdfContent);
RandomAccessReadBuffer buffer = new RandomAccessReadBuffer(bais);
PDDocument document = Loader.loadPDF(buffer)) {
PDFRenderer renderer = new PDFRenderer(document);
int numPages = document.getNumberOfPages();
if (numPages == 0) {
return null;
}
List<BufferedImage> pageImages = new ArrayList<>();
int totalHeight = 0;
int maxWidth = 0;
for (int i = 0; i < numPages; i++) {
BufferedImage pageImage = renderer.renderImageWithDPI(i, 150);
pageImages.add(pageImage);
totalHeight += pageImage.getHeight();
maxWidth = Math.max(maxWidth, pageImage.getWidth());
}
BufferedImage stitchedImage = new BufferedImage(maxWidth, totalHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = stitchedImage.createGraphics();
g2d.setBackground(java.awt.Color.WHITE);
g2d.clearRect(0, 0, maxWidth, totalHeight);
int yOffset = 0;
for (BufferedImage pageImage : pageImages) {
g2d.drawImage(pageImage, 0, yOffset, null);
yOffset += pageImage.getHeight();
}
g2d.dispose();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(stitchedImage, "png", baos);
return baos.toByteArray();
} catch (Exception e) {
throw new IOException("PDF轉(zhuǎn)圖片失敗", e);
}
}
}
3.如何使用
byte[] imageBytes = new DocumentToImageUtil().convertToStitchedImage(content, fileType.toLowerCase());
到此這篇關(guān)于Java實現(xiàn)將Word和PDF轉(zhuǎn)成一張垂直拼接長圖的工具類的文章就介紹到這了,更多相關(guān)Java Word和PDF轉(zhuǎn)圖片內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java中循環(huán)刪除list中元素的方法總結(jié)
下面小編就為大家?guī)硪黄猨ava中循環(huán)刪除list中元素的方法總結(jié)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12
Java14發(fā)布了,再也不怕NullPointerException了
這篇文章主要介紹了Java14發(fā)布了,再也不怕NullPointerException了,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2020-03-03
spring boot@EnableXXXX注解編程模型講解
這篇文章主要介紹了spring boot@EnableXXXX注解編程模型,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09

