所需jar包地址
<!-- java 读取word文件里面的加颜色的字体 转pdf 使用 -->
<dependency>
<groupId> e-iceblue </groupId>
<artifactId>spire.doc.free</artifactId>
<version>3.9.0</version>
</dependency>
<!--poi 的相关组件 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</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>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.2</version>
</dependency>
<!-- 不添加此包会提示错误 : org.openxmlformats.schemas.wordprocessingml.x2006.main.FontsDocument$Factory -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>org.apache.poi.xwpf.converter.pdf</artifactId>
<version>1.0.6</version>
</dependency>
<!-- 用于 word 转pdf -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>xdocreport</artifactId>
<version>2.0.2</version>
</dependency>
<!-- pdf 添加水印 对PDF文件的操作 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.1</version>
</dependency>
<!-- PDF文件 字体 防止中文乱码 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<!--基于 poi实现word数据的替换 -->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.9.1</version>
</dependency>
<!--
如果下载jar失败,说明下载jar失败,需要以下的maven依赖
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException
-->
<repository>
<id>com.e-iceblue</id>
<url>http://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
<!-- <dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.25</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>org.apache.poi.xwpf.converter.xhtml</artifactId>
<version>1.0.6</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.document</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>org.apache.poi.xwpf.converter.core</artifactId>
<version>1.0.6</version>
</dependency>-->
<!-- 打包使用,需要配置 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!-- 打包时会将本地jar一起打包 -->
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
执行代码main方法运行
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.*;
import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import java.io.*;
public class TestWordToPDF {
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
String docxPath = "C:\\Users\\admin-xu\\Desktop\\11\\test.docx";
String pdfPath = "C:\\Users\\admin-xu\\Desktop\\11\\test2.pdf";
File file = new File( docxPath);
InputStream inputStream = new FileInputStream(file);
ByteArrayOutputStream pdfBaos = new ByteArrayOutputStream();
XWPFDocument xwpfDocument = new XWPFDocument(inputStream);
fr.opensagres.poi.xwpf.converter.pdf.PdfConverter.getInstance().convert(xwpfDocument, pdfBaos, PdfOptions.create());
inputStream.close();
xwpfDocument.close();
byte[] pdfArray = null;
pdfArray = pdfBaos.toByteArray();
pdfBaos.close();
InputStream pdfInputStream = new ByteArrayInputStream( pdfArray ) ;
FileOutputStream fileOutputStream = new FileOutputStream(pdfPath);
addWaterMark(pdfInputStream , fileOutputStream);
long end = System.currentTimeMillis();
System.out.println("执行时间: " + ((end - start) / 1000) + "秒");
}
//给PDF文件添加水印
public static void addWaterMark(InputStream pdfInputStream , FileOutputStream fileOutputStream) {
try {
// 原PDF文件
PdfReader reader = new PdfReader(pdfInputStream);
// 输出的PDF文件内容
PdfStamper pdfStamper = new PdfStamper(reader, fileOutputStream );
// 字体 来源于 itext-asian JAR包
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", true);
PdfGState pdfGState = new PdfGState();
// 设置透明度
pdfGState.setFillOpacity(0.2f);
pdfGState.setStrokeOpacity(0.4f);
int totalPage = reader.getNumberOfPages() + 1;
for (int i = 1; i < totalPage; i++) {
// 内容上层
// PdfContentByte content = stamper.getOverContent(i);
// 内容下层
PdfContentByte pdfContentByte = pdfStamper.getUnderContent(i);
pdfContentByte.beginText();
// 字体添加透明度
pdfContentByte.setGState(pdfGState);
// 添加字体大小等
pdfContentByte.setFontAndSize(baseFont, 20);
// 添加范围
pdfContentByte.setTextMatrix(70, 200);
// 具体位置 内容 多少行 多少列 旋转多少度 共360度
for (int a = 0; a < 3; a++) { // 一页几排
for (int j = 0; j < 3; j++) { // 一排几个
int x = 70 + 170 * j ; // 横向 宽
int y = 170 + 200 * a ; // 纵向 高
pdfContentByte.showTextAligned(Element.ALIGN_BOTTOM, "机密文件" , x, y, 45); // 45 是水印旋转的角度
}
}
pdfContentByte.endText();
}
// 关闭
pdfStamper.close();
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
转换前的word
转换后的 pdf
执行结果和时间,项目中实际测试大概是5-6秒左右(和服务器性能相关)
实际代码使用,通过浏览器下载
// 转换后 通过浏览器下载
// word 替换数据后 下载 // /replaceWordToPDF/exportWordPDF
@GetMapping(value = "/exportWordPDF")
public R<?> exportWordTest(@RequestParam Map<String , Object> mapCon, HttpServletResponse response) throws Exception {
long a1 = System.currentTimeMillis();
R resultBody = replaceWordDataService.replaceWord( mapCon );
if(resultBody.getCode() == 0 ){
byte[] array = null;
ExportWordDTO data = (ExportWordDTO) resultBody.getData();
XWPFTemplate template = data.getXwpfTemplate();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
template.writeAndClose( baos );//文档写入流
array = baos.toByteArray();
baos.close();
template.close();
// 替换后的word转流
InputStream inputStream = new ByteArrayInputStream( array ) ;
ByteArrayOutputStream pdfBaos = new ByteArrayOutputStream();
long a2 = System.currentTimeMillis();
// word 转pdf
XWPFDocument xwpfDocument = new XWPFDocument(inputStream);
fr.opensagres.poi.xwpf.converter.pdf.PdfConverter.getInstance().convert(xwpfDocument, pdfBaos, PdfOptions.create());
inputStream.close();
xwpfDocument.close();
byte[] pdfArray = null;
pdfArray = pdfBaos.toByteArray();
pdfBaos.close();
// pdf 文件
InputStream pdfInputStream = new ByteArrayInputStream( pdfArray ) ;
response.setContentType("application/octet-stream");
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode( data.getOutFileName()+".pdf", "UTF-8"));
OutputStream out = response.getOutputStream();
long a3 = System.currentTimeMillis();
// 添加水印
// 原PDF文件
PdfReader reader = new PdfReader(pdfInputStream);
// 输出的PDF文件内容
PdfStamper stamper = new PdfStamper(reader, out);
// 字体 来源于 itext-asian JAR包
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", true);
PdfGState gs = new PdfGState();
// 设置透明度
gs.setFillOpacity(0.2f);
gs.setStrokeOpacity(0.4f);
int totalPage = reader.getNumberOfPages() + 1;
System.out.println( totalPage );
for (int i = 1; i < totalPage; i++) {
// 内容上层
// PdfContentByte content = stamper.getOverContent(i);
// 内容下层
PdfContentByte content = stamper.getUnderContent(i);
content.beginText();
// 字体添加透明度
content.setGState(gs);
// 添加字体大小等
content.setFontAndSize(baseFont, 20);
// 添加范围
content.setTextMatrix(70, 200);
// 具体位置 内容 旋转多少度 共360度 复制艺术字并设置多行多列位置 ( 设置几排 ) // 多少列
for (int a = 0; a < 3; a++) { // 一页几排
for (int j = 0; j < 3; j++) { // 一排几个
int x = 70 + 170 * j ; // 横向 宽
int y = 170 + 200 * a ; // 纵向 高
content.showTextAligned(Element.ALIGN_BOTTOM, "户用光伏电站签约专用" , x, y, 45);
}
}
content.endText();
}
// 关闭
stamper.close();
reader.close();
pdfInputStream.close();
out.close();
long a4 = System.currentTimeMillis();
System.out.println("word替换时间: " + ((a2 - a1) ) + "毫秒");
System.out.println("word转pdf时间: " + ((a3 - a2) ) + "毫秒");
System.out.println("添加水印时间: " + ((a4 - a3) ) + "毫秒");
System.out.println("共计用时: " + ((a4 - a1) ) + "毫秒");
PoitlIOUtils.closeQuietlyMulti(template, out);
return null;
}else {
return R.fail().msg(resultBody.getMsg());
}
}
获取转换后的pdf byte[]数组数组
注意这里有个坑 在关闭流的时候才往(输出流)写内容了,上面只是定义 并没有写到输入流 ByteArrayOutputStream,放到close上面是没数据的,只能放到 close 的下面,因为这一步才开始写数据
// word 替换数据后 转换 pdf 添加水印后 获取字节数组 通过字节数组上传到文件服务器
@GetMapping(value = "/exportWordTestUrl")
public R<?> exportWordTestUrl(@RequestParam Map<String , Object> mapCon ) throws Exception {
R resultBody = replaceWordDataService.replaceWord( mapCon );
if(resultBody.getCode() == 0 ){
byte[] array = null;
ExportWordDTO data = (ExportWordDTO) resultBody.getData();
XWPFTemplate template = data.getXwpfTemplate();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
template.writeAndClose( baos );//文档写入流
array = baos.toByteArray();
baos.close();
template.close();
// 替换后的word转流
InputStream inputStream = new ByteArrayInputStream( array ) ;
ByteArrayOutputStream pdfBaos = new ByteArrayOutputStream();
// word 转pdf
XWPFDocument xwpfDocument = new XWPFDocument(inputStream);
fr.opensagres.poi.xwpf.converter.pdf.PdfConverter.getInstance().convert(xwpfDocument, pdfBaos, PdfOptions.create());
inputStream.close();
xwpfDocument.close();
byte[] pdfArray = null;
pdfArray = pdfBaos.toByteArray();
pdfBaos.close();
// pdf 文件
InputStream pdfInputStream = new ByteArrayInputStream( pdfArray ) ;
ByteArrayOutputStream out = new ByteArrayOutputStream();
// 添加水印
// 原PDF文件
PdfReader reader = new PdfReader(pdfInputStream);
// 输出的PDF文件内容
PdfStamper stamper = new PdfStamper(reader, out );
// 字体 来源于 itext-asian JAR包
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", true);
PdfGState gs = new PdfGState();
// 设置透明度
gs.setFillOpacity(0.2f);
gs.setStrokeOpacity(0.4f);
int totalPage = reader.getNumberOfPages() + 1;
for (int i = 1; i < totalPage; i++) {
// 内容上层
// PdfContentByte content = stamper.getOverContent(i);
// 内容下层
PdfContentByte content = stamper.getUnderContent(i);
content.beginText();
// 字体添加透明度
content.setGState(gs);
// 添加字体大小等
content.setFontAndSize(baseFont, 20);
// 添加范围
content.setTextMatrix(70, 200);
// 具体位置 内容 旋转多少度 共360度 复制艺术字并设置多行多列位置 ( 设置几排 ) // 多少列
for (int a = 0; a < 3; a++) { // 一页几排
for (int j = 0; j < 3; j++) { // 一排几个
int x = 70 + 170 * j ; // 横向 宽
int y = 170 + 200 * a ; // 纵向 高
content.showTextAligned(Element.ALIGN_BOTTOM, "户用光伏电站签约专用" , x, y, 45);
}
}
content.endText();
}
pdfInputStream.close();
// 注意这里有个坑 在关闭流的时候才往(输出流)写内容了,上面只是定义 并没有写到输入流 ByteArrayOutputStream,放到close上面是没数据的,只能放到 close 的下面,
// 因为这一步才开始写数据
stamper.close();
reader.close();
byte[] bytes = out.toByteArray();
out.close();
PoitlIOUtils.closeQuietlyMulti(template, out);
R<ResultFileModel> upload = remoteFileService.upload(bytes, 1, applicationName, "户光伏电站签约专用.pdf");
if (null != upload && upload.getCode() == 0){
// 将url 存入数据库
ResultFileModel fileModel = upload.getData();
String path = fileModel.getAddress() + fileModel.getPath();
replaceWordDataService.updatePdfUrl( path , mapCon.get("-data_id-") .toString() );
return R.ok().data("添加成功");
}else {
return R.fail().msg( "文件上传失败!" );
}
}
return R.fail().msg(resultBody.getMsg());
}
另外一种方法
java word转换pdf(先自定义添加水印 后转换pdf)_My--Style的博客-CSDN博客