一、下载或配置:
下载jar包 :freemaker的jar包下载 下载jar包 :aspose-words的jar包下载
或者配置maven依赖: pom.xml添加aspose的依赖包(maven仓库不提供aspose您可以下载并添加依赖包maven仓库)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <dependency> <groupId>com.aspose</groupId> <artifactId>aspose-words</artifactId> <version>15.12.0</version> </dependency>
二、创建模板文件:
1.先新建一个word文档,将 word 需要填写的数据占位符${变量名}替换。
效果如下:
2.将word文档另存为xml格式文件。
效果如下:
3.用Notepad 打开xml模板文件,把<w:binData >标签中的图片base64编码删除,占位符${变量名}替换。
4.处理复选框(000A三、未选状态 ,0052:选择状态),使用if,else在标签上写一个逻辑判断gender =="1"勾(男)复选框,gender =="2"勾(女)复选框。
(如果复选框标签显示 <w:t>?</w:t>将以下标签替换到您复选框显示的位置)
<w:sym w:font="Wingdings 2" w:char="00A3"/>
5.将xml文件模板后缀改为ftl保存文件格式。
三、开始测试:
生成word文档,word转pdf,pdf预览和下载工具
package com.text.util; import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.aspose.words.Document;
import com.aspose.words.SaveFormat;
import freemarker.core.ParseException;
import freemarker.log.Logger;
import freemarker.template.Configuration;
import freemarker.template.MalformedTemplateNameException;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateNotFoundException;
import org.apache.commons.lang.StringUtils;
/** * Word转PDF工具类 * @author luvJie-7c * */
public class WordToPdfUtil {
private static Logger log = Logger.getLogger(WordToPdfUtil.class.toString());
/** * * @param dataMap 要填充的数据 * @param templateName 模版名称 * @param fileName 要输出的文件名称 * @param CoType 文件类型 * @throws Exception */
public static String createWord(Map<String, String> dataMap, String templateName, String fileName,String CoType) throws Exception {
long start = System.currentTimeMillis();
//定义pdf路径
String pdfPath = "";
HttpServletRequest request = ServletActionContext.getRequest();
try {
//设置FreeMarker的版本和编码格式 版本和jar包版本要一致
Configuration config =new Configuration(Configuration.VERSION_2_3_22);
config.setDefaultEncoding("UTF-8");
//设置FreeMarker生成Word文档所需要的模板路径 webapp/ftl文件夹下
config.setDirectoryForTemplateLoading(new File(request.getSession().getServletContext().getRealPath("/ftl")));
Template template = null;
try {
//设置FreeMarker生成Word文档所需要的模板
template = config.getTemplate(templateName,"UTF-8");
} catch (TemplateNotFoundException e) {
log.error("模板文件未找到", e);
e.printStackTrace();
} catch (MalformedTemplateNameException e) {
log.error("模板类型不正确", e);
e.printStackTrace();
} catch (ParseException e) {
log.error("解析模板出错,请检查模板格式", e);
e.printStackTrace();
} catch (IOException e) {
log.error("IO读取失败", e);
e.printStackTrace();
}
//创建日期年月日 组文件路径
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd");
String dfDate = df.format(new Date());
String dateYear = dfDate.substring(0,4);
String dateMonth = dfDate.substring(5,7);
String dateDay = dfDate.substring(8,10);
//定义pdf路径
pdfPath = "/pdf/"+ CoType + "/" + dateYear + "/"+ dateMonth + "/" + dateDay +"/";
//存放路径
String path = ServletActionContext.getServletContext().getRealPath(pdfPath);
//创建文件夹
File f = new File(path+fileName+".doc");
//判断文件夹是否存在,不存在,则新建一个文件夹
if (!f.getParentFile().exists()) {
f.getParentFile().mkdirs();
}
//创建一个Word文档输出流
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), "UTF-8"));
try {
template.process(dataMap, out);
} catch (TemplateException e) {
log.error("填充模板时异常", e);
e.printStackTrace();
} catch (IOException e) {
log.error("IO读取时异常", e);
e.printStackTrace();
}
log.info("由模板文件:" + templateName + " 生成文件 :" + fileName + ".doc" + " 成功!!");
out.flush();
out.close();
//word文档转PDF
wordOrPdf(path+fileName+".doc", null);
//pdf路径
pdfPath = pdfPath+fileName+".pdf";
log.info("由Word文档:" + fileName + " 生成文件 :" + fileName.replace(".doc", ".pdf") + "" + " 成功!!");
log.info("文档生成地址:"+path+fileName+".pdf");
long end = System.currentTimeMillis();
log.info("文档生成耗时:" + ((end - start) / 1000.0) + "秒");
} catch (Exception e) {
e.printStackTrace();
log.info("Word模板生成失败!!");
}
return pdfPath;
}
/** * 使用aspose.word把word文档转为pdf文档 * * @param sourceFile word文档绝对路径 * @param destFile pdf文档绝对路径 */
public static String wordOrPdf(String sourceFile, String destFile) throws Exception {
destFile = StringUtils.isEmpty(destFile) ? sourceFile.replace(".doc", ".pdf") : destFile;
// 验证License 若不验证则转化出的pdf文档会有水印产生
if (!getLicense()) {
throw new Exception("生成PDF文档,验证License失败!");
}
try {
File file = new File(destFile); //新建一个空白pdf文档
FileOutputStream os = new FileOutputStream(file);
Document doc = new Document(sourceFile);//通过sourceFile创建word文档对象
//本地项目不设置此路径 只针对服务器上的字体文件路径
//FontSettings.setFontsFolder("/usr/share/fonts/windowsFont/", true);
doc.save(os, SaveFormat.PDF);
os.close();
} catch (Exception e) {
e.printStackTrace();
throw new Exception("生成PDF文档失败!");
}
return destFile;
}
/** * @Description: 验证aspose.word组件是否授权:无授权的文件有水印标记 */
public static boolean getLicense() {
boolean result = false;
try {
String s = "<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>";
ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes());
com.aspose.words.License license = new com.aspose.words.License();
license.setLicense(inputStream);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/** * pdf文档预览、下载 * @param fileName 文件名称 * @param path 路径 * @throws Exception */
public static void previewPdf(String fileName, String path) throws Exception{
if(isFileCz(path)){
// 验证该文件是否是存在
HttpServletResponse response = ServletActionContext.getResponse();
//设置PDF格式 名称
response.setHeader("Access-Control-Allow-Origin", "*");
//以流的形式传输
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; fileName="+fileName+".pdf");
try {
//输入输出
FileInputStream is = new FileInputStream(ServletActionContext.getServletContext().getRealPath(path));
ServletOutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
int i = 0;
while ((i = is.read(buffer)) != -1) {
out.write(buffer,0,i);
}
log.info("已输出Pdf文档:"+fileName+".pdf");
out.flush();
out.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/** * 判断文件是否是存在 存在返回true * @param yzfile 要验证的文件路径 * @return */
public static boolean isFileCz(String yzfile){
String s0 = ServletActionContext.getRequest().getRealPath(yzfile);
File file = new File(s0);
if(!file.exists()){
return false;
}
return true;
}
}
调用工具类:
HashMap<String, String> hashMap = new HashMap<String, String>(); hashMap.put("name", "测试"); //存入一个图片的base64编码 hashMap.put("img", "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"); hashMap.put("gender", "1"); try { //返回pdf路径 String pdfPath = WordToPdfUtil.createWord(hashMap, "测试文档.ftl", "测试文档", "Ct"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
文档生成地址:
word文档效果如下:
pdf文档效果如下: