java ftl doc转换为pdf_freemarker动态生成word并将生成的word转为PDF,openoffice转换word乱码...

这篇博客介绍了一个Java项目需求,即动态生成Word内容后再预览,使用Freemarker和XML操作实现。首先尝试通过Freemarker将XML转换为Word,但由于转换PDF时出现乱码问题,改为修改docx文件的XML内容。通过将模板文件中的内容用Freemarker表达式替换,然后使用特定工具和库将docx转换为PDF。整个过程中涉及的关键步骤包括XML的格式化、动态数据填充、以及OpenOffice进行转换。此外,博客还提到了所需依赖项和OpenOffice的设置。
摘要由CSDN通过智能技术生成

之前项目有个需求,需要先动态生成word内容,然后再预览生成word的内容(不能修改).整理一下,方便以后使用.

网上参考了好多大神的博客.具体也忘了参考谁的了,如有侵权,请告知修改.

思路一:

将目标word文件另存为xml文件,将里面的需要动态生成的内容用freemarker的表达式${}替换.

用freemarker生成word的工具类,动态生成word. 这样生成的word实际上是xml文件,用办公软件能正常打开使用.

但是转pdf的时候发现转不成功.转过之后的pdf显示的不是word的格式字符,而是像xml文件的标签及字符,失败!

思路二:

word的docx文件其实属于zip的一种. 这里只需要对它的核心内容部分进行操作.其他数据不动.具体做法为:

1.用办公软件(wps/office)打开模板文件,将需要修改的内容,用freemarker的表达式${}替换.

(注意:需要循环展示的内容还需要在xml文件中处理)如下:

bef96f6e51772edfc362baf2b4240ff7.png

2.将模板docx文件重命名为.zip的压缩文件.

3.用解压工具打开,取出word/document.xml 文件.

e6324dabfde4add5e9a7e7fb9ecba5b1.png

4.此时用文本工具打开document.xml,内容不太好看,将文件格式化一下.(我这里没找到好的格式化工具,使用notepad没格好,最后用idea还行).格式化后如下.

c70ea86184a6f6f2b71accc24b355335.png

5.在xml中需要循环的内容前增加如下标签:

fe0ff6f097f45bb3a2f69373673acc61.png

6.说明

word中要填充的数据为map格式,${}中为map的key.如果还需要循环填充可以如下操作:

map1   map2   list

map1.put("username",name);

list.add(map1);

map2.put("list",list);

map2.put("title",title);

map2即为要填充的所有数据.这样给list一个别名listkey 后,${}中如下填写即可.

12b2fba44dbd54d748d939b69a54fdb5.png

7.将模板文件与xml文件保存到一个固定位置.我这里保存到了项目中:

cc81d277ece18d363d01c50e6c098a86.png

8.准备工作完成,生成word工具类如下:

import freemarker.template.templateexception;

import java.io.*;

import java.util.enumeration;

import java.util.map;

import java.util.zip.zipentry;

import java.util.zip.zipexception;

import java.util.zip.zipfile;

import java.util.zip.zipoutputstream;

/**

* 其实docx属于zip的一种,这里只需要操作word/document.xml中的数据,其他的数据不用动

*

* @author

*

*/

public class xmltodocx {

/**

*

* @param xmltemplate xml的文件名

* @param docxtemplate docx的路径和文件名

* @param xmltemp 填充完数据的临时xml

* @param tofilepath 目标文件名

* @param map 需要动态传入的数据

* @throws ioexception

* @throws templateexception

*/

public static void todocx(string xmltemplate,string docxtemplate,string xmltemp ,string tofilepath,map map) {

try {

// 1.map是动态传入的数据

// 这个地方不能使用filewriter因为需要指定编码类型否则生成的word文档会因为有无法识别的编码而无法打开

writer w1 = new outputstreamwriter(new fileoutputstream(xmltemp), "gb2312");

// 2.把map中的数据动态由freemarker传给xml

xmltplutil.process(xmltemplate, map, w1);

// 3.把填充完成的xml写入到docx中

xmltodocx xtd = new xmltodocx();

xtd.outdocx(new file(xmltemp), docxtemplate, tofilepath);

}catch (exception e) {

e.printstacktrace();

}

}

/**

*

* @param documentfile 动态生成数据的docunment.xml文件

* @param docxtemplate docx的模板

* @param tofilepath 需要导出的文件路径

* @throws zipexception

* @throws ioexception

*/

public void outdocx(file documentfile, string docxtemplate, string tofilepath) throws zipexception, ioexception {

try {

file docxfile = new file(docxtemplate);

zipfile zipfile = new zipfile(docxfile);

enumeration extends zipentry> zipentrys = zipfile.entries();

zipoutputstream zipout = new zipoutputstream(new fileoutputstream(tofilepath));

int len = -1;

byte[] buffer = new byte[1024];

while (zipentrys.hasmoreelements()) {

zipentry next = zipentrys.nextelement();

inputstream is = zipfile.getinputstream(next);

// 把输入流的文件传到输出流中 如果是word/document.xml由我们输入

zipout.putnextentry(new zipentry(next.tostring()));

if ("word/document.xml".equals(next.tostring())) {

inputstream in = new fileinputstream(documentfile);

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();

}

}

}

9.生成pdf工具类

import com.artofsolving.jodconverter.documentconverter;

import com.artofsolving.jodconverter.openoffice.connection.openofficeconnection;

import com.artofsolving.jodconverter.openoffice.connection.socketopenofficeconnection;

import com.artofsolving.jodconverter.openoffice.converter.openofficedocumentconverter;

import org.apache.poi.xwpf.converter.pdf.pdfconverter;

import org.apache.poi.xwpf.converter.pdf.pdfoptions;

import org.apache.poi.xwpf.usermodel.xwpfdocument;

import java.io.*;

public class xmltodoc {

/**

* 生成pdf

*/

public static string makepdfbyxcode(string docx) {

string filename = null;

file outfile = null;

try {

// document.setparagraph(new pa );

if (docx.contains(".docx")) {

xwpfdocument document=new xwpfdocument(new fileinputstream(new file(docx)));

outfile=new file(docx.replace(".docx",".pdf"));

filename=docx.replace(".docx",".pdf");

outfile.getparentfile().mkdirs();

outputstream out=new fileoutputstream(outfile);

// ifontprovider fontprovider = new abstractfontregistry();

pdfoptions options= pdfoptions.create(); //gb2312

pdfconverter.getinstance().convert(document,out,options);

} else {

file inputfile = new file(docx);

outfile = new file(docx.replace(".doc", ".pdf"));

filename = docx.replace(".doc", ".pdf");

outfile.getparentfile().mkdirs();

openofficeconnection connection = new socketopenofficeconnection(8100);

connection.connect();

// convert

documentconverter converter = new openofficedocumentconverter(connection);

converter.convert(inputfile, outfile);

// close the connection

connection.disconnect();

}

}catch (illegalargumentexception e){

system.err.println("未知文件格式");

}

catch (exception e) {

e.printstacktrace();

}

return filename;

}

}

import freemarker.template.configuration;

import freemarker.template.template;

import freemarker.template.templateexception;

import java.io.file;

import java.io.ioexception;

import java.io.writer;

import java.util.map;

public class xmltplutil {

private static xmltplutil tplm = null;

private configuration cfg = null;

private xmltplutil() {

cfg = new configuration();

try {

// 注册tmlplate的load路径

// 这的路径是xml的路径

string pathname = xmltplutil.class.getclassloader().getresource("").getpath();

string path = pathname.substring(1, pathname.lastindexof("/"));

string parentpath1 = new file(path).getparent();//获取项目的上一级目录

string parentpath2 = new file(parentpath1).getparent();//获取项目的上一级目录

string xmlpath = parentpath2 + "/static/excelmodel";

cfg.setdirectoryfortemplateloading(new file(xmlpath));

} catch (exception e) {

e.printstacktrace();

}

}

private static template gettemplate(string name) throws ioexception {

if (tplm == null) {

tplm = new xmltplutil();

}

template template = tplm.cfg.gettemplate(name);

return template;

}

/**

*

* @param templatefile 模板文件

* @param param 需要填充的内容

* @param out 填充完成输出的文件

* @throws ioexception

* @throws templateexception

*/

public static void process(string templatefile, map param, writer out) throws ioexception, templateexception {

// 获取模板

template template = xmltplutil.gettemplate(templatefile);

template.setoutputencoding("gbk");

// 合并数据

template.process(param, out);

if (out != null) {

out.close();

}

}

}

注意:生成pdf需要安装openoffice 软件,安装完成后,

cd openoffice目录下有个openoffice 4\program

然后输入命令

soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard

就ok了.

10.用到的maven包

com.artofsolving

jodconverter

2.2.1

org.openoffice

jurt

3.0.1

org.openoffice

ridl

3.0.1

org.openoffice

juh

3.0.1

org.openoffice

unoil

3.0.1

fr.opensagres.xdocreport

org.apache.poi.xwpf.converter.pdf

1.0.6

org.freemarker

freemarker

2.3.22

---------------------

作者:菜鸟-也-想飞

来源:csdn

原文:https://blog.csdn.net/qq_21306669/article/details/84313569

注意:springboot打成jar无法放入webapp下生成,

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值