摘要
本文通过使用word模板文件,替换文件中的参数,转化为PDF文件放入response流实现PDF下载。话不多说,进入正题
导入依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>xdocreport</artifactId>
<version>1.0.6</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.11</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
工具类
package com.solvay.utils.file;
import com.alibaba.nacos.common.http.HttpUtils;
import com.itextpdf.text.Document;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.apache.poi.ooxml.POIXMLDocument;
import org.apache.poi.xwpf.usermodel.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Entities;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* @author syb
* @date 2022/9/24
*/
public class OfficeToPdfUtil {
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
/**
* html转为pdf
* @param html
* @return
*/
public static byte[] htmlToPdf(String html) {
com.itextpdf.text.Document document = null;
ByteArrayInputStream bais = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] resBytes = null;
try {
document = new com.itextpdf.text.Document(PageSize.A4);
PdfWriter writer = PdfWriter.getInstance(document, baos);
document.open();
bais = new ByteArrayInputStream(html.getBytes());
XMLWorkerHelper.getInstance().parseXHtml(writer, document, bais, Charset.forName("UTF-8"), new FontProvider() {
@Override
public boolean isRegistered(String s) {
return false;
}
@Override
public Font getFont(String s, String s1, boolean embedded, float size, int style, BaseColor baseColor) {
// 配置字体
Font font = null;
try {
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
font = new Font(bf, size, style, baseColor);
font.setColor(baseColor);
} catch (Exception e) {
e.printStackTrace();
}
return font;
}
});
document.close();
writer.close();
resBytes = baos.toByteArray();
} catch (Exception e) {
log.error("html转pdf异常:{}",e);
} finally {
if (document != null) {
document.close();
}
if (bais != null) {
try {
bais.close();
} catch (IOException e) {
log.error("html转pdf关闭io流异常:{}",e);
}
}
}
return resBytes;
}
/**
* doc文件转为html
* @param inputStream
* @return
* */
public static String doc2Html(InputStream inputStream) {
String content = null;
ByteArrayOutputStream baos = null;
try {
HWPFDocument wordDocument = new HWPFDocument(inputStream);
WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
wordToHtmlConverter.setPicturesManager(new PicturesManager() {
@Override
public String savePicture(byte[] content, PictureType pictureType, String suggestedName, float widthInches, float heightInches) {
return null;
}
});
wordToHtmlConverter.processDocument(wordDocument);
org.w3c.dom.Document htmlDocument = wordToHtmlConverter.getDocument();
DOMSource domSource = new DOMSource(htmlDocument);
baos = new ByteArrayOutputStream();
StreamResult streamResult = new StreamResult(baos);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty(OutputKeys.METHOD, "html");
serializer.transform(domSource, streamResult);
} catch (Exception e) {
log.error("doc转html异常:{}",e);
} finally {
try {
if (baos != null) {
content = new String(baos.toByteArray(), "utf-8");
baos.close();
}
} catch (Exception e) {
log.error("doc转html关闭io流异常:{}",e);
}
}
return content;
}
/**
* 使用jsoup规范化html
* @param html html内容
* @return 规范化后的html
*/
public static String formatHtml(String html) {
org.jsoup.nodes.Document doc = Jsoup.parse(html);
// 去除过大的宽度
String style = doc.attr("style");
if (StringUtils.isNotEmpty(style) && style.contains("width")) {
doc.attr("style", "");
}
Elements divs = doc.select("div");
for (org.jsoup.nodes.Element div : divs) {
String divStyle = div.attr("style");
if (StringUtils.isNotEmpty(divStyle) && divStyle.contains("width")) {
div.attr("style", "");
}
}
// jsoup生成闭合标签
doc.outputSettings().syntax(org.jsoup.nodes.Document.OutputSettings.Syntax.xml);
doc.outputSettings().escapeMode(Entities.EscapeMode.xhtml);
return doc.html();
}
//docx转PDF
public static byte[] docxToPdf(InputStream src) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] resBytes = null;
String result;
try {
// pdf文件的尺寸
Document pdfDocument = new Document(PageSize.A3, 72, 72, 72, 72);
PdfWriter pdfWriter = PdfWriter.getInstance(pdfDocument, baos);
XWPFDocument doc = new XWPFDocument(src);
pdfWriter.setInitialLeading(20);
java.util.List<XWPFParagraph> plist = doc.getParagraphs();
pdfWriter.open();
pdfDocument.open();
for (int i = 0; i < plist.size(); i++) {
XWPFParagraph pa = plist.get(i);
java.util.List<XWPFRun> runs = pa.getRuns();
for (int j = 0; j < runs.size(); j++) {
XWPFRun run = runs.get(j);
java.util.List<XWPFPicture> piclist = run.getEmbeddedPictures();
Iterator<XWPFPicture> iterator = piclist.iterator();
while (iterator.hasNext()) {
XWPFPicture pic = iterator.next();
XWPFPictureData picdata = pic.getPictureData();
byte[] bytepic = picdata.getData();
Image imag = Image.getInstance(bytepic);
pdfDocument.add(imag);
}
// 中文字体的解决
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font font = new Font(bf, 11.0f, Font.NORMAL, BaseColor.BLACK);
String text = run.getText(-1);
byte[] bs;
if (text != null) {
bs = text.getBytes();
String str = new String(bs);
Chunk chObj1 = new Chunk(str, font);
pdfDocument.add(chObj1);
}
}
pdfDocument.add(new Chunk(Chunk.NEWLINE));
}
//需要关闭,不然无法获取到输出流
pdfDocument.close();
pdfWriter.close();
resBytes = baos.toByteArray();
} catch (Exception e) {
log.error("docx转pdf文件异常:{}",e);
}finally {
try{
if(baos != null){
baos.close();
}
}catch (IOException e){
log.error("docx转pdf关闭io流异常:{}",e);
}
}
return resBytes;
}
//word参数填充
public static XWPFDocument newWord(Map<String, String> map, String srcPath) {
XWPFDocument document = null;
try {
URL url = new URL(srcPath);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
document = new XWPFDocument(conn.getInputStream());
// document = new XWPFDocument(POIXMLDocument.openPackage(srcPath));
} catch (IOException e) {
e.printStackTrace();
}
Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();
while (itPara.hasNext()) {
XWPFParagraph paragraph = (XWPFParagraph) itPara.next();
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
String oneparaString = run.getText(run.getTextPosition());
if (StringUtils.isBlank(oneparaString) || !oneparaString.contains("$")){
continue;
}
for (Map.Entry<String, String> entry :
map.entrySet()) {
oneparaString = oneparaString.replace(entry.getKey(), entry.getValue());
}
run.setText(oneparaString, 0);
}
}
return document;
}
//docx转PDF
public static byte[] docxToPdf(XWPFDocument doc) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] resBytes = null;
String result;
try {
// pdf文件的尺寸
Document pdfDocument = new Document(PageSize.A3, 72, 72, 72, 72);
PdfWriter pdfWriter = PdfWriter.getInstance(pdfDocument, baos);
pdfWriter.setInitialLeading(20);
java.util.List<XWPFParagraph> plist = doc.getParagraphs();
pdfWriter.open();
pdfDocument.open();
for (int i = 0; i < plist.size(); i++) {
XWPFParagraph pa = plist.get(i);
java.util.List<XWPFRun> runs = pa.getRuns();
for (int j = 0; j < runs.size(); j++) {
XWPFRun run = runs.get(j);
java.util.List<XWPFPicture> piclist = run.getEmbeddedPictures();
Iterator<XWPFPicture> iterator = piclist.iterator();
while (iterator.hasNext()) {
XWPFPicture pic = iterator.next();
XWPFPictureData picdata = pic.getPictureData();
byte[] bytepic = picdata.getData();
Image imag = Image.getInstance(bytepic);
pdfDocument.add(imag);
}
// 中文字体的解决
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font font = new Font(bf, 11.0f, Font.NORMAL, BaseColor.BLACK);
String text = run.getText(-1);
byte[] bs;
if (text != null) {
bs = text.getBytes();
String str = new String(bs);
Chunk chObj1 = new Chunk(str, font);
pdfDocument.add(chObj1);
}
}
pdfDocument.add(new Chunk(Chunk.NEWLINE));
}
//需要关闭,不然无法获取到输出流
pdfDocument.close();
pdfWriter.close();
resBytes = baos.toByteArray();
} catch (Exception e) {
log.error("docx转pdf文件异常:{}",e);
}finally {
try{
if(baos != null){
baos.close();
}
}catch (IOException e){
log.error("docx转pdf关闭io流异常:{}",e);
}
}
return resBytes;
}
}
使用示例
OutputStream bos = new BufferedOutputStream(response.getOutputStream());
//map为替换参数,如替换文件中的${name},map中存放key为${name}value为测试。即可替换掉文件中的参数为测试
//filePath为模板文件存放的url地址
XWPFDocument xwpfDocument = OfficeToPdfUtil.newWord(map, filePath);
bos.write(OfficeToPdfUtil.docxToPdf(xwpfDocument));
bos.flush();
标签:word,String,import,org,baos,new,PDF,null,模板
From: https://www.cnblogs.com/simplejavahome/p/16737197.html