之前的一平文档介绍了基于freemark生成doc的技术,但是生成的doc底层还是xml文件,在转化为pdf后,pdf内容全部为xml,参考网上的生成docx教程,自己尝试下,记录如下:
1、新建一个docx文档
新建一个docx文档:test.docx,内容还是使用占位符。
2、修改后缀为zip,把里面word目录下的document.xml作为模板。
3、生成docx
准备文档的数据,替换模板中的占位符,并把替换后包含数据的模板替换掉zip中的document.xml。
public static void main(String[] args) throws Exception{
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("date","2019年8月22日");
Configuration configuration = new Configuration();
configuration.setClassForTemplateLoading(DocUtil.class, "/template/");
Template template = configuration.getTemplate("document.xml");
String outFilePath = "D:\\data.xml";
File docFile = new File(outFilePath);
FileOutputStream fos = new FileOutputStream(docFile);
Writer out = new BufferedWriter(new OutputStreamWriter(fos),10240);
template.process(dataMap,out);
out.close();
ZipInputStream zipInputStream = ZipUtils.wrapZipInputStream(new FileInputStream(new File("D:\\test.zip")));
ZipOutputStream zipOutputStream = ZipUtils.wrapZipOutputStream(new FileOutputStream(new File("D:\\test.docx")));
String itemname = "word/document.xml";
ZipUtils.replaceItem(zipInputStream, zipOutputStream, itemname, new FileInputStream(new File("D:\\data.xml")));
}
public class ZipUtils {
/**
* 替换某个 item,
*
* @param zipInputStream zip文件的zip输入流
* @param zipOutputStream 输出的zip输出流
* @param itemName 要替换的 item 名称
* @param itemInputStream 要替换的 item 的内容输入流
*/
public static void replaceItem(ZipInputStream zipInputStream, ZipOutputStream zipOutputStream,
String itemName, InputStream itemInputStream) {
//
if (null == zipInputStream) {
return;
}
if (null == zipOutputStream) {
return;
}
if (null == itemName) {
return;
}
if (null == itemInputStream) {
return;
}
//
ZipEntry entryIn;
try {
while ((entryIn = zipInputStream.getNextEntry()) != null) {
String entryName = entryIn.getName();
ZipEntry entryOut = new ZipEntry(entryName);
// 只使用 name
zipOutputStream.putNextEntry(entryOut);
// 缓冲区
byte[] buf = new byte[8 * 1024];
int len;
if (entryName.equals(itemName)) {
// 使用替换流
while ((len = (itemInputStream.read(buf))) > 0) {
zipOutputStream.write(buf, 0, len);
}
} else {
// 输出普通Zip流
while ((len = (zipInputStream.read(buf))) > 0) {
zipOutputStream.write(buf, 0, len);
}
}
// 关闭此 entry
zipOutputStream.closeEntry();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
close(itemInputStream);
close(zipInputStream);
close(zipOutputStream);
}
}
/**
* 包装输入流
*/
public static ZipInputStream wrapZipInputStream(InputStream inputStream) {
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
return zipInputStream;
}
/**
* 包装输出流
*/
public static ZipOutputStream wrapZipOutputStream(OutputStream outputStream) {
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
return zipOutputStream;
}
private static void close(InputStream inputStream) {
if (null != inputStream) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void close(OutputStream outputStream) {
if (null != outputStream) {
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
正确生成docx文档:
参考: