本文采用XDocReport集合Freemaiker进行处理
1. 引入Maven依赖:
fr.opensagres.xdocreport
xdocreport
2.0.1
org.apache.velocity
velocity-engine-core
2.0
org.freemarker
freemarker
2.3.23
2. 创建Word模版
新建Word,在光标处通过快捷键Ctrl+F9 或 工具栏“插入”->“文档部件或文本”->“域”
根据电脑系统不同出现的界面不同,但内容都差不多,${text} 这个text就是后期要替换的变量了。
3. Java代码处理逻辑
1 String templateFilePath = request.getSession().getServletContext().getRealPath("/WEB-INF/templates/freemarkerTest.docx");2 File file = newFile(templateFilePath);3 InputStream in = newFileInputStream(file);4 IXDocReport report;5 String targetPath = basePath + lawDownDto.getLawsName() + ".docx";6 try{7 report =XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker);8 //设置内容为HTML格式
9 FieldsMetadata metadata =report.createFieldsMetadata();10 metadata.addFieldAsTextStyling("text", SyntaxKind.Html);11
12 //创建内容-text为模版中对应都变量名称
13 IContext context =report.createContext();14 context.put("text", content);15
16 //生成文件
17 OutputStream out = newFileOutputStream(targetPath);18 report.process(context, out);19 } catch(XDocReportException e) {20 e.printStackTrace();21 }
文件下载:在生成文件逻辑后创建读取流返回即可。
=============================================================
如果文件中有图片需要处理:
图片方案一:单个图片且位置固定,可通过XDocReport配置模版处理
图片方案二:多个图片且位置不固定,可通过POI结合Freemarker进行处理
图片方案一:
1. 在模版中插入临时图片,选中图片并添加“书签”,书签名称是后续作为替换的变量
2. 代码中追加逻辑
在上面代码10后追加
//logo为模版中标签名称
metadata.addFieldAsImage("logo");
report.setFieldsMetadata(metadata);
在上面代码14行后追加
//IImageProvider可通过3种方式创建(File/IO流/ClassPath下文件)具体可参考顶部文档-Dynamic Image
IImageProvider logo = new FileImageProvider(new File("1950737_195902644.png"));
context.put("logo", logo);
图片方案二:
1. 在上面读取模版之前进行数据替换
//处理文本中的图片,使用imgReplace变量替换
Map param = new HashMap();if(StringUtils.isNotBlank(content)) {
content=HtmlUtils.htmlUnescape(content);
List> imgs =getImgStrContent(content);int count = 0;for (HashMapimg : imgs) {
count++;//处理替换以“/>”结尾的img标签
content = content.replace(img.get("img"), "${imgReplace" + count + "}");//处理替换以“>”结尾的img标签
content = content.replace(img.get("img1"), "${imgReplace" + count + "}");
Map header = new HashMap();
String result= "";
result= img.get("src");//如果没有宽高属性,默认设置为
if(img.get("width") == null || img.get("height") == null) {
header.put("width", 150);
header.put("height", 150);
}else{
header.put("width", (int)(Double.parseDouble(img.get("width"))));
header.put("height", (int) (Double.parseDouble(img.get("height"))));
}if( StringUtils.isNotBlank(result) ){
String type1= result.substring(result.lastIndexOf(".") , result.length());
header.put("type", type1);
header.put("content",this.imageToInputStream(result));
}
param.put("${imgReplace" + count + "}", header);
}
}
//获取html中的图片元素信息
private List>getImgStrContent(String htmlStr) {
List> pics = new ArrayList>();
Document doc=Jsoup.parse(htmlStr);if( doc != null){
Elements imgs= doc.select("img");if( imgs != null && imgs.size() > 0){for(Element img : imgs) {
HashMap map = new HashMap();if(!"".equals(img.attr("width"))) {
map.put("width", img.attr("width"));
}if(!"".equals(img.attr("height"))) {
map.put("height", img.attr("height"));
}
map.put("img", img.toString().substring(0, img.toString().length() - 1) + "/>");
map.put("img1", img.toString());
map.put("src", img.attr("src"));
pics.add(map);
}
}
}returnpics;
}
//读取生成的文件
readStream = newFileInputStream(targetPath);
ByteArrayOutputStream docxOs= newByteArrayOutputStream();int b = 0;byte[] buf = new byte[1024];while ((b = readStream.read(buf)) != -1) {
docxOs.write(buf,0, b);
}
docxResponseStream= newByteArrayInputStream(docxOs.toByteArray());//创建word 对象
XWPFDocument document = newXWPFDocument(docxResponseStream);
newOS= newByteArrayOutputStream();if (document != null && param != null) {//生成带图片的word(如需工具类请给我发邮件)
XWPFDocument customXWPFDocument =WordUtil.getWord(param, document);//设置表格边框样式(另外一片文章会介绍)//List list = formatTableBorder(customXWPFDocument);//处理合并单元格(另外一片文章会介绍)//mergeCell(content, list);//写入输出流返回
customXWPFDocument.write(newOS);
document.close();
customXWPFDocument.close();
resultInpu= newByteArrayInputStream(newOS.toByteArray());
}else{
resultInpu=docxResponseStream;
}
以上内容即可完成Word中多图片的动态展示。
后续会写处理表格边框、单元格合并及段落都相关内容。