实现思路:先利用word做出模板,转成程序可进行操作的xml文件,再利用freemarker处理成带数据的真实文件,然后再转成pdf,前端页面中直接预览打印。
用到的第三方资源:
1.aspose-words-15.8.0-jdk16.jar
2.aspose-cells-8.5.2.jar
3.freemarker.jar
本例子支持生成文件及数据流,因为一般情况下生成word和转换为pdf是同时进行的,所以这里推荐采用了流的形式进行转换及展示,主要代码如下:
因为aspose是收费的,所以这里有一个破解版,就是在项目中放一个License.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<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>
相应的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-demo2</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/freemarker/freemarker -->
<dependency>
<groupId>freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.9</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
TestController.java 其中word方法只支持生成word文件,word2pdf方法是已文件的形式生成pdf,word2pdf_byte方法是已流的形式生成pdf
package com.example.demo.controller;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.example.demo.util.FreeMarkerUtil;
import com.example.demo.util.PdfUtil;
import com.example.demo.util.QRCodeGenerator;
import com.google.zxing.WriterException;
@Controller
public class TestController {
@RequestMapping("/word")
public void word(HttpServletResponse response) throws IOException{
String imagestr = null;
try {
imagestr = QRCodeGenerator.getQRCodeImageStr("test", 360, 360);
} catch (WriterException e) {
System.out.println("Could not generate QR Code, WriterException :: " + e.getMessage());
e.printStackTrace();
}
Map<String, Object> map = new HashMap<String, Object>();
map.put("qrCodeImage", imagestr);
map.put("title1", "标题一");
map.put("title2", "标题二");
map.put("title3", "标题三");
map.put("title4", "标题四");
map.put("title5", "标题五");
map.put("value1", "描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1");
map.put("value2", "描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2");
map.put("value3", "描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3");
map.put("value4", "描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4");
map.put("value5", "描述5描述5描述5描述5描述5描述5描述5描述5描述5描述5描述5描述5描述5");
//下载word文档
File file = null;
InputStream fin = null;
ServletOutputStream out = null;
try {
// 调用工具类WordGenerator的createDoc方法生成Word文档
file = FreeMarkerUtil.createDoc(map, "qrCode");
fin = new FileInputStream(file);
response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
// 设置浏览器以下载的方式处理该文件默认名为resume.doc
response.addHeader("Content-Disposition","attachment;filename="+ UUID.randomUUID() +".doc");
out = response.getOutputStream();
byte[] buffer = new byte[512]; // 缓冲区
int bytesToRead = -1;
// 通过循环将读入的Word文件的内容输出到浏览器中
while ((bytesToRead = fin.read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);
}
} finally {
if (fin != null)
fin.close();
if (out != null)
out.close();
if (file != null)
file.delete(); // 删除临时文件
}
}
@RequestMapping("/word2pdf")
@ResponseBody
public String word2pdf(HttpServletResponse response) throws IOException{
String imagestr = null;
try {
imagestr = QRCodeGenerator.getQRCodeImageStr("test", 360, 360);
} catch (WriterException e) {
System.out.println("Could not generate QR Code, WriterException :: " + e.getMessage());
e.printStackTrace();
}
Map<String, Object> map = new HashMap<String, Object>();
map.put("qrCodeImage", imagestr);
map.put("title1", "标题一");
map.put("title2", "标题二");
map.put("title3", "标题三");
map.put("title4", "标题四");
map.put("title5", "标题五");
map.put("value1", "描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1");
map.put("value2", "描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2");
map.put("value3", "描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3");
map.put("value4", "描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4");
map.put("value5", "描述5描述5描述5描述5描述5描述5描述5描述5描述5描述5描述5描述5描述5");
File file = FreeMarkerUtil.createDoc(map, "qrCode");
System.out.println(file.getAbsolutePath());
PdfUtil.doc2pdf(file.getAbsolutePath(), "d:\\test.pdf");
return "success";
}
@RequestMapping("/word2pdf_byte")
public void word2pdf_byte(HttpServletResponse response) throws IOException{
String imagestr = null;
try {
imagestr = QRCodeGenerator.getQRCodeImageStr("test", 360, 360);
} catch (WriterException e) {
System.out.println("Could not generate QR Code, WriterException :: " + e.getMessage());
e.printStackTrace();
}
Map<String, Object> map = new HashMap<String, Object>();
map.put("qrCodeImage", imagestr);
map.put("title1", "标题一");
map.put("title2", "标题二");
map.put("title3", "标题三");
map.put("title4", "标题四");
map.put("title5", "标题五");
map.put("value1", "描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1描述1");
map.put("value2", "描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2描述2");
map.put("value3", "描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3描述3");
map.put("value4", "描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4描述4");
map.put("value5", "描述5描述5描述5描述5描述5描述5描述5描述5描述5描述5描述5描述5描述5");
byte[] bytes = FreeMarkerUtil.createDocByte(map, "qrCode");
ByteArrayOutputStream outputStream = PdfUtil.docByte2pdfByte(bytes);
response.getOutputStream().write(outputStream.toByteArray());
// File file = FreeMarkerUtil.createDoc(map, "qrCode");
// System.out.println(file.getAbsolutePath());
// PdfUtil.doc2pdf(file.getAbsolutePath(), "d:\\test.pdf");
}
}
FreeMarkerUtil.java 这里demo采用的是springboot框架,所以将静态资源放在/static/tpl/文件夹中
package com.example.demo.util;
import freemarker.template.Configuration;
import freemarker.template.Template;
import sun.misc.BASE64Encoder;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class FreeMarkerUtil {
private static Configuration configuration = null;
private static HashMap<String, Template> allTemplates = null;
static {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
configuration.setClassForTemplateLoading(FreeMarkerUtil.class,"/static/tpl/");//模板ftl文件在templates下面
/*
* allTemplates = new HashMap<>();
*/
allTemplates = new HashMap<String, Template>();
try {
allTemplates.put("qrCode", configuration.getTemplate("qrCode.ftl"));
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static File createDoc(Map<?, ?> dataMap, String type) {
String name = "temp" + (int) (Math.random() * 100000) + ".doc";
File f = new File(name);
// Template t = allTemplates.get(type);
try {
Template t = configuration.getTemplate(type + ".ftl");
// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
t.process(dataMap, w);
w.close();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
return f;
}
public static byte[] createDocByte(Map<?, ?> dataMap, String type) {
// Template t = allTemplates.get(type);
ByteArrayOutputStream byteArrayOutputStream = null;
try {
Template t = configuration.getTemplate(type + ".ftl");
// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
byteArrayOutputStream = new ByteArrayOutputStream();
Writer w = new OutputStreamWriter(byteArrayOutputStream);
t.process(dataMap, w);
w.close();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
return byteArrayOutputStream.toByteArray();
}
}
PdfUtil.java: 其中license.xml文件可以根据实际的项目配置到自定义的路径
package com.example.demo.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import com.aspose.cells.Workbook;
import com.aspose.words.Document;
import com.aspose.words.License;
/**
* Word或Excel 转Pdf 帮助类
* @author lenovo
* 备注:需要引入 aspose-words-15.8.0-jdk16.jar / aspose-cells-8.5.2.jar
*/
public class PdfUtil {
private static boolean getLicense() {
boolean result = false;
try {
InputStream is = PdfUtil.class.getClassLoader().getResourceAsStream("license.xml"); // license.xml应放在..\WebRoot\WEB-INF\classes路径下
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* @param wordPath 需要被转换的word全路径带文件名
* @param pdfPath 转换之后pdf的全路径带文件名
*/
public static void doc2pdf(String wordPath, String pdfPath) {
if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
return;
}
try {
long old = System.currentTimeMillis();
File file = new File(pdfPath); //新建一个pdf文档
FileOutputStream os = new FileOutputStream(file);
Document doc = new Document(wordPath); //Address是将要被转化的word文档
doc.save(os, com.aspose.words.SaveFormat.PDF);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
long now = System.currentTimeMillis();
os.close();
System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒"); //转化用时
} catch (Exception e) {
e.printStackTrace();
}
}
public static void docByte2pdf(byte[] bytesWord, String pdfPath) {
if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
return;
}
ByteArrayInputStream byteArrayInputStream = null;
try {
long old = System.currentTimeMillis();
File file = new File(pdfPath); //新建一个pdf文档
FileOutputStream os = new FileOutputStream(file);
byteArrayInputStream = new ByteArrayInputStream(bytesWord);
Document doc = new Document(byteArrayInputStream);
doc.save(os, com.aspose.words.SaveFormat.PDF);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
long now = System.currentTimeMillis();
os.close();
System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒"); //转化用时
} catch (Exception e) {
e.printStackTrace();
}
}
public static ByteArrayOutputStream docByte2pdfByte(byte[] bytesWord) {
if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
return null;
}
ByteArrayInputStream byteArrayInputStream = null;
ByteArrayOutputStream byteArrayOutputStream = null;
try {
long old = System.currentTimeMillis();
byteArrayOutputStream = new ByteArrayOutputStream();
byteArrayInputStream = new ByteArrayInputStream(bytesWord);
Document doc = new Document(byteArrayInputStream);
doc.save(byteArrayOutputStream, com.aspose.words.SaveFormat.PDF);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
long now = System.currentTimeMillis();
byteArrayOutputStream.close();
byteArrayInputStream.close();
System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒"); //转化用时
} catch (Exception e) {
e.printStackTrace();
}
return byteArrayOutputStream;
}
/**
* @param excelPath 需要被转换的excel全路径带文件名
* @param pdfPath 转换之后pdf的全路径带文件名
*/
public static void excel2pdf(String excelPath, String pdfPath) {
if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
return;
}
try {
long old = System.currentTimeMillis();
Workbook wb = new Workbook(excelPath);// 原始excel路径
FileOutputStream fileOS = new FileOutputStream(new File(pdfPath));
wb.save(fileOS, com.aspose.cells.SaveFormat.PDF);
fileOS.close();
long now = System.currentTimeMillis();
System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒"); //转化用时
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//word 和excel 转为pdf
String filePaths="D:/logs/Java多线程大合集.doc";
String fileName="zsqexcel78";
String pdfPath="D:/logs/"+fileName+".pdf";
//doc2pdf(filePaths, pdfPath);//filePaths需要转换的文件位置 pdfPath为存储位置
String excel2pdf="D:/logs/excelToPdf.xlsx";
excel2pdf(excel2pdf,pdfPath);
}
}
本文暂时没有评论,来添加一个吧(●'◡'●)