准备好空白的word模板
在需要的字段中填写字段名称
如果需要插入图片的地方需要优先插入备用图片
将word文档另存存为xml格式
这里说明一下,使用office和使用wps是有错位编码的,根据应用习惯去进行word的格式化
将生成的xml文件复制一份,并更改后缀名为ftl文件
正常的pom文件以外还要引入以下库
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-freemarkerartifactId>
dependency>
<dependency>
<groupId>commons-iogroupId>
<artifactId>commons-ioartifactId>
<version>2.6version>
dependency>
<dependency>
<groupId>com.documents4jgroupId>
<artifactId>documents4j-localartifactId>
<version>1.0.3version>
dependency>
<dependency>
<groupId>com.documents4jgroupId>
<artifactId>documents4j-transformer-msoffice-wordartifactId>
<version>1.0.3version>
dependency>
package cc.vace.cloud.str.util;
import cc.vace.cloud.str.util.SpringUtil;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.IOUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import java.io.*;
import java.util.Map;
public final class FreemarkerParseUtils {
/**
* a不可实例化
*/
private FreemarkerParseUtils() {
}
/**
* a把ftl文件解析成html字符串内容
*
* @param templatePath ftl文件路径
* @param model 模型数据(插值)
* @return 解析后的html文件内容
*/
public static String parse(String templatePath, Map<String, Object> model) {
StringWriter stringWriter = null;
BufferedWriter writer = null;
File f = new File(templatePath);
if (!f.getParentFile().exists()) {
f.getParentFile().mkdirs();
}
try {
//获取模板
Template template = SpringUtil
.getBean("freeMarkerConfigurer", FreeMarkerConfigurer.class)
.getConfiguration()
.getTemplate(templatePath);
stringWriter = new StringWriter();
writer = new BufferedWriter(stringWriter);
//将模板与数据模型合并
template.process(model, writer);
writer.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(writer);
IOUtils.closeQuietly(stringWriter);
}
return stringWriter.toString();
}
/**
* a解析ftl文件内容
*
* @param content 原ftl模板文件内容
* @param model 模板文件数据
* @return 解析后的html文件内容
*/
public static String parseFtlContent(String content, Map<String, Object> model) {
// 获取配置
StringWriter out = new StringWriter();
try {
Template template = new Template("template", new StringReader(content),
SpringUtil.getBean("freeMarkerConfigurer", FreeMarkerConfigurer.class).getConfiguration());
template.process(model, out);
} catch (TemplateException | IOException e) {
return "";
}
String htmlContent = out.toString();
if (out != null) {
try {
out.close();
} catch (IOException e) {
return "";
}
}
return htmlContent;
}
}
2.SpringUtil
package cc.vace.cloud.str.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
System.out.println("========ApplicationContext配置成功,在普通类可以通过调用SpringUtils.getAppContext()获取applicationContext对象,applicationContext=" + SpringUtil.applicationContext + "========");
System.out.println("---------------------------------------------------------------------");
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
package cc.vace.cloud.str.util;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import sun.misc.BASE64Encoder;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 图片工具类
*/
@Component
public class ImageUtil {
/**
* 将图片内容转换成Base64编码的字符串
* @param imageFile 图片文件的全路径名称
* @return 转换成Base64编码的图片内容字符串
*/
public static String getImageBase64String(String imageFile) {
if (StringUtils.isEmpty(imageFile)) {
return "";
}
File file = new File(imageFile);
if (!file.exists()) {
return "";
}
InputStream is = null;
byte[] data = null;
try {
is = new FileInputStream(file);
data = new byte[is.available()];
is.read(data);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return Base64.encodeBase64String(data);
}
}
package cc.vace.cloud.str.util;
import com.documents4j.api.DocumentType;
import com.documents4j.api.IConverter;
import com.documents4j.job.LocalConverter;
import freemarker.core.ParseException;
import freemarker.template.*;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class TemplateUtil {
/**
* a生成word文件
*
* @param dataMap 模板中需要展示的动态数据,用map集合来保存
* @param templateName 模板名称
* @param fileCompletePath 输出文件完整路径,例如:D:/wordFile/
* @throws IOException
* @throws ParseException
* @throws MalformedTemplateNameException
* @throws TemplateNotFoundException
* @throws TemplateException
*/
public static void createFile(Map dataMap, String templateName, String fileCompletePath) throws Exception {
File file = new File(fileCompletePath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
// 创建配置实例
Configuration configuration = new Configuration();
// 设置编码
configuration.setDefaultEncoding("UTF-8");
// ftl模板文件
configuration.setClassForTemplateLoading(TemplateUtil.class, "/");
// 获取模板
Template template = configuration.getTemplate(templateName);
// 输出文件
File outFile = new File(fileCompletePath);
// 如果输出目标文件夹不存在,则创建
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();
}
public static void createTemplateAndConverter(Map dataMap, String templateName, String fileCompletePath) throws Exception {
// 创建配置实例
Configuration configuration = new Configuration();
// 设置编码
configuration.setDefaultEncoding("UTF-8");
// ftl模板文件
configuration.setClassForTemplateLoading(TemplateUtil.class, "/");
// 获取模板
Template template = configuration.getTemplate(templateName);
// 将模板和数据模型合并生成文件
// Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Writer writer = new BufferedWriter(new OutputStreamWriter(byteArrayOutputStream, "UTF-8"));
// 生成文件
template.process(dataMap, writer);
File file = new File(fileCompletePath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
OutputStream outputStream = new FileOutputStream(file);
IConverter converter = LocalConverter.builder().baseFolder(new File(file.getParentFile().getPath())).build();
converter.convert(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())).as(DocumentType.DOCX).to(outputStream).as(DocumentType.PDF).execute();
}
public static void main(String[] args) throws Exception {
Map map = new HashMap();
// map数据,模板,
createFile(map,"templates/csdn.ftl","D:/csdn_generate.doc");
}
}
这时我们的文件时这个样子的
格式化一下代码
在ftl文件中,有可能会需要更改里边我们设置的参数
将多余的标签删除,直到参数为实际参数为止
最终效果(如果本来就是${参数}可以不用修改)
找到图片base64编码区域,将编码删除,设置成我们的图片参数
<pkg:part pkg:name="/word/media/image1.png" pkg:contentType="image/png" pkg:compression="store">
<pkg:binaryData>${img1}pkg:binaryData>
pkg:part>
这里需要注意,如果你是多张图片位置,但是在设置模板的时候为同一个图片,则只会有一个图片包出现,需要自己添加新的图片包
找到Relationships中的image1.png,在文件中有多个Relationships,一定要找到image1.png的Relationship
在后面追加
根据image1.png的id:rtd4搜索找到应用的地方
或者
修改其中一个改成我们自己写的ID就可以啦
@Autowired
TemplateUtil templateUtil;
@Override
public void test(BaseQuery query) {
Map map = new HashMap();
map.put("name","张三");
map.put("id","202145154545");
map.put("sex","男的");
map.put("nation","汉族");
map.put("img1",ImageUtil.getImageBase64String("C:/Users/king/Desktop/hh.png"));
//图片路径,并由ImageUtil生成base64编码格式
map.put("img2",ImageUtil.getImageBase64String("C:/Users/king/Desktop/mz.png"));
//"template/blog.ftl":指向模板
//"D:/blog1.doc":生成的文件路径以及文件名
templateUtil.createFile(map,"template/blog.ftl","D:/blog1.doc");
}