当前位置: 移动技术网 > IT编程>开发语言>Java > freemarker动态生成word并将生成的word转为PDF,openoffice转换word乱码

freemarker动态生成word并将生成的word转为PDF,openoffice转换word乱码

2019年04月26日  | 移动技术网IT编程  | 我要评论

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

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

思路一:

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

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

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

思路二:

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

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

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

 

 

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

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

 

 

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

 

 

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

 

 

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 后,${}中如下填写即可.

 

 

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

 

 

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包

<dependency>
<groupid>com.artofsolving</groupid>
<artifactid>jodconverter</artifactid>
<version>2.2.1</version>
</dependency>
<!--openoffice-->
<dependency>
<groupid>org.openoffice</groupid>
<artifactid>jurt</artifactid>
<version>3.0.1</version>
</dependency>
<dependency>
<groupid>org.openoffice</groupid>
<artifactid>ridl</artifactid>
<version>3.0.1</version>
</dependency>
<dependency>
<groupid>org.openoffice</groupid>
<artifactid>juh</artifactid>
<version>3.0.1</version>
</dependency>
<dependency>
<groupid>org.openoffice</groupid>
<artifactid>unoil</artifactid>
<version>3.0.1</version>
</dependency>
<dependency>
<groupid>fr.opensagres.xdocreport</groupid>
<artifactid>org.apache.poi.xwpf.converter.pdf</artifactid>
<version>1.0.6</version>
</dependency>
<dependency>
<groupid>org.freemarker</groupid>
<artifactid>freemarker</artifactid>
<version>2.3.22</version>
</dependency>
---------------------
作者:菜鸟-也-想飞
来源:csdn
原文:https://blog.csdn.net/qq_21306669/article/details/84313569

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网