1.制作模板为动态导出做准备
因为转pdf需要docx格式。所有先弄一个word模板。
保存后再复制一个将后缀名改为zip压缩包的格式。解压取出document.xml和document.xml.rels。
document.xml对图片的设置
document.xml.rels设置动态图片地址
这样模板就配好了。
2.maven配置
<!-- 如果只是想实现word导出,只需要这一个包:freemarker就行了 -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
<!-- 导出pdf需要使用的包:xdocreport -->
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>org.apache.poi.xwpf.converter.core</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>org.apache.poi.xwpf.converter.pdf</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>fr.opensagres.xdocreport</groupId>
<artifactId>fr.opensagres.xdocreport.itext.extension</artifactId>
<version>1.0.4</version>
</dependency>
3.生成word
/**
* @param dataMap 参数数据
* @param docxTemplate docx模主板名称
* @param xmltemplateName xml主模板名称
* @param xmltConfigemplateName xml配置主模板名称 一般用来配置图片、样式信息
* @param temp_path 模板存放路径
* @param base_path 模板实际路径
* @param output_path 产出路径
* @param output_file_name 产出文件名称
*/
public static void createDocx(Map dataMap, String docxTemplate, String xmltemplateName, String xmltConfigemplateName, String temp_path, String base_path, String output_path, String output_file_name) {
try {
try {
//================================拼装生成xml配置文档================================
String xml_config_output_path = output_path + System.currentTimeMillis() + ".xml.rels";
createTemplateXml(dataMap, xmltConfigemplateName, temp_path, xml_config_output_path);
File xmlConfigFile = new File(xml_config_output_path);
//读取 xmlConfigFile 文件 并获取rId 与 图片的关系
String xmlConfigFile_content = getFreemarkerContent(dataMap, xmltConfigemplateName, temp_path);
System.out.println("===========================xmlConfigFile_content================================");
System.out.println(xmlConfigFile_content);
System.out.println("===========================xmlConfigFile_content================================");
Document document = DocumentHelper.parseText(xmlConfigFile_content);
Element rootElt = document.getRootElement(); // 获取根节点
Iterator iter = rootElt.elementIterator();// 获取根节点下的子节点head
List<String> warn_list = new ArrayList<>();
// 遍历Relationships节点
while (iter.hasNext()) {
Element recordEle = (Element) iter.next();
String id = recordEle.attribute("Id").getData().toString();
String target = recordEle.attribute("Target").getData().toString();
if (target.indexOf("media") == 0) {
// System.out.println("id>>>"+id+" >>>"+target);
// id>>>rId18 >>>media/pic1
warn_list.add(id);
}
}
dataMap.put("warn_list", warn_list);
// dataMap.put("","");
//================================拼装生成xml配置文档================================
//================================拼装生成主模板xml文档================================
String xml_output_path = output_path + System.currentTimeMillis() + ".xml";
createTemplateXml(dataMap, xmltemplateName, temp_path, xml_output_path);
File xmlFile = new File(xml_output_path);
//================================拼装生成主模板xml文档================================
File docxFile = new File(base_path + docxTemplate);
if (!docxFile.exists()) {
docxFile.createNewFile();
}
ZipFile zipFile = new ZipFile(docxFile);
Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(output_path + output_file_name));
int len = -1;
byte[] buffer = new byte[1024];
//------------------追加新图片------------------
// List<String> picList = new ArrayList<>();
Map<String, String> picFiles = (Map<String, String>) dataMap.get("pics");
if (picFiles != null && !picFiles.isEmpty()) {
for (String fileName : picFiles.keySet()) {
ZipEntry next = new ZipEntry("word" + File.separator + "media" + File.separator + fileName);
zipout.putNextEntry(new ZipEntry(next.toString()));
InputStream in = new FileInputStream(picFiles.get(fileName));
while ((len = in.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
in.close();
}
}
//------------------追加新图片------------------
len = -1;
while (zipEntrys.hasMoreElements()) {
ZipEntry next = zipEntrys.nextElement();
InputStream is = zipFile.getInputStream(next);
// 把输入流的文件传到输出流中 如果是word/document.xml由我们输入
zipout.putNextEntry(new ZipEntry(next.toString()));
System.out.println(">>>>>>>>>" + next.isDirectory());
System.out.println(">>>>>>>>>>>>>>>>>" + next.toString());
System.out.println(">>>>>>>>>>>>>>>>>" + next.isDirectory());
if ("word/document.xml".equals(next.toString())) {
InputStream in = new FileInputStream(xmlFile);
while ((len = in.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
in.close();
} else if (next.toString().indexOf("document.xml.rels") > 0) {
InputStream in = new FileInputStream(xmlConfigFile);
while ((len = in.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
in.close();
} else {
while ((len = is.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
is.close();
}
}
zipout.close();
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 生成主数据模板xml
*
* @param dataMap 数据参数
* @param templateName 模板名称
* @param pathPrefix 模板路径
* @param filePath 生成路径
*/
public static void createTemplateXml(Map dataMap, String templateName, String pathPrefix, String filePath) {
try {
//创建配置实例
Configuration configuration = new Configuration();
//设置编码
configuration.setDefaultEncoding("UTF-8");
//ftl模板文件统一放至 com.lun.template 包下面
configuration.setDirectoryForTemplateLoading(new File(path + "template/"));
// configuration.setClassForTemplateLoading(FreemarkerWordUtils.class,"/template/doc");
//configuration.setClassForTemplateLoading(WordToPDFUtil.class, pathPrefix);
//获取模板
Template template = configuration.getTemplate(templateName);
//输出文件
File outFile = new File(filePath);
//如果输出目标文件夹不存在,则创建
if (!outFile.getParentFile().exists()) {
outFile.getParentFile().mkdirs();
}
//将模板和数据模型合并生成文件
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
//生成文件
template.process(dataMap, out);
//关闭流
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getFreemarkerContent(Map dataMap, String templateName, String temp_path) {
String ret_str = "";
try {
//创建配置实例
Configuration configuration = new Configuration();
//设置编码
configuration.setDefaultEncoding("UTF-8");
//ftl模板文件统一放至 com.lun.template 包下面
configuration.setDirectoryForTemplateLoading(new File(path + "template/"));
//configuration.setClassForTemplateLoading(WordToPDFUtil.class, temp_path);
//获取模板
Template template = configuration.getTemplate(templateName);
//输出文件
//File outFile = new File(filePath);
//如果输出目标文件夹不存在,则创建
// if (!outFile.getParentFile().exists()){
// outFile.getParentFile().mkdirs();
// }
//将模板和数据模型合并生成文件
// Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
StringWriter swriter = new StringWriter();
//生成文件
template.process(dataMap, swriter);
ret_str = swriter.toString();
} catch (Exception e) {
e.printStackTrace();
}
return ret_str;
}
4.word 转pdf
/**
* word转pdf
* @param wordPath word的路径
* @param pdfPath pdf的路径
*/
public static boolean wordToPdf(String wordPath, String pdfPath){
logger.info("wordPath:{}, pdfPath:{}", wordPath, pdfPath);
boolean result = false;
try {
logger.info("开始word转pdf");
XWPFDocument document=new XWPFDocument(new FileInputStream(new File(wordPath)));
File outFile=new File(pdfPath);
outFile.getParentFile().mkdirs();
OutputStream out=new FileOutputStream(outFile);
PdfOptions options= PdfOptions.create();
PdfConverter.getInstance().convert(document,out,options);
logger.info("word转pdf成功");
result = true;
}
catch ( Exception e) {
e.printStackTrace();
logger.error("word转pdf失败");
}
return result;
}
5.测试
public static String details = "珍琴是一名孤儿,八岁时被人领养并读华兴小学,11岁时,她读三年级,便遇到了小熙老师,小熙老师是她的代课老师,教英语。她是初中毕业然后读三年中专,毕完业后在华兴当三年级的代课老师。\n" +
" \n" +
" 她年轻开朗,活泼可爱。由于珍琴的英语老师怀孕了,所以课都是有小熙老师来上的,珍琴很有学英语的天赋,所以她成功的当上了小熙老师的课代表,珍琴很乖,很懂事,她上课也很认真,下课也不吵不闹,她工作认真负责。作业按时交齐,经常抽查背诵……小熙老师很喜欢她,她也很喜欢小熙老师。\n" +
" \n" +
" 但是那段时间,珍琴的养父母生了个儿子,根本没有时间,也没有精力去照顾珍琴,她一个人要扫地,拖地……干很多活,所以她总是在学校写完作业才回家。那是夏末初秋,一般她回家时都是太阳落山了,有一天她回家的路上,遇见了小熙老师,小熙老师问她怎么这么晚才回家,珍琴沉迷了许久才说嗯,我把作业都写完了……小熙老师对她笑了笑说,“上来吧,我送你回家。”说完,小熙老师指着她后面的后排座,珍琴有些犹豫,小熙老师摸了摸她的头说,“没事的,刚好顺路。来。\n" +
" \n" +
" 珍琴点点头,然后上去了,从此放学的每一天都是小熙老师送她回家的,直到有一天,小熙老师找到珍琴说,“对不起,今天我可能没有办法送你回家了,以后可能也没有办法了,不好意思。”珍琴摆摆手说没事,随后递给了她一个棒棒糖,小熙老师望着那根棒棒糖,然后问她,你喜欢吃棒棒糖啊?珍琴点点头,小熙老师摸了摸她的头,然后说谢谢。";
public static final String path = "D:/下载文件/git/mybatis/src/main/resources/";
public static final String xmltemplateName = "document.xml";//xml主模板名称
public static final String xmltConfigemplateName = "document.xml.rels";//xml配置主模板名称 一般用来配置图片、样式信息
public static void main(String[] args) {
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("Edition", "v_1.0");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dataMap.put("date", sdf.format(new Date()));
//用户图片
List<String> picList = new ArrayList<>();
Map<String, String> pics = new HashMap<>();
picList.add("summary_9.png");
pics.put("summary_9.png", "D:\\迅雷下载\\summary_9.png");
picList.add("summary_4.png");
pics.put("summary_4.png", "D:\\迅雷下载\\summary_4.png");
picList.add("summary_3.png");
pics.put("summary_3.png", "D:\\迅雷下载\\summary_3.png");
picList.add("summary_2.png");
pics.put("summary_2.png", "D:\\迅雷下载\\summary_2.png");
dataMap.put("picList", picList);
dataMap.put("pics", pics);
dataMap.put("details", details);
String output_path = path + "static/";
String output_file_name = "test.docx";
String base_path = path + "template/";
createDocx(dataMap, "test.docx", "document.xml",
"document.xml.rels", path + "template/",
base_path, output_path, output_file_name);
WordAndPdfUtil.wordToPdf(output_path + "test.docx", output_path + "test.pdf");
}
6效果
word
pdf