方法1 直接用docx文件,填充模板数据,转换为图片,base64,发送html模板邮件
方法2 docx文件另存为htm,移除无用标签,模板替换变量,转图片,base64,发送html模板邮件
docx直接用aspose 工具,转换
<!-- docx模板转换工具 -->
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>15.8.0</version>
</dependency>
/***
* 填充数据
* @param templatePath
* @param data
* @param fileType
*/
public static String fillWordDataByMapToBase64(String templatePath, Map<String, Object> data, int fileType) {
try {
InputStream is = SysUserWorkServiceImpl.class.getResourceAsStream("/aspose/license.xml");
License license = new License();
license.setLicense(is);
} catch (Exception e) {
log.error("自动加载aspose证书文件失败!");
// throw new RuntimeException("自动加载aspose证书文件失败!");
}
ByteArrayOutputStream dstStream = new ByteArrayOutputStream();
try (InputStream is = new FileInputStream(templatePath);) {
Document doc = new Document(is);
DocumentBuilder builder = new DocumentBuilder(doc);
Map<String, String> toData = new HashMap<>();
for (Map.Entry<String, Object> en : data.entrySet()) {
String key = en.getKey();
Object value = en.getValue();
if (key == null || value == null) {
continue;
}
if (value instanceof List) {
//写入表数据
DataTable dataTable = fillListData((List) value, key);
doc.getMailMerge().executeWithRegions(dataTable);
}
if (value instanceof BufferedImage) {
builder.moveToMergeField(key);
builder.insertImage((BufferedImage) value);
}
String valueStr = String.valueOf(en.getValue());
toData.put(key, valueStr);
}
String[] fieldNames = new String[toData.size()];
String[] values = new String[toData.size()];
int i = 0;
for (Map.Entry<String, String> entry : toData.entrySet()) {
fieldNames[i] = entry.getKey();
values[i] = entry.getValue();
i++;
}
//合并数据
doc.getMailMerge().execute(fieldNames, values);
doc.save(dstStream, SaveOptions.createSaveOptions(fileType));
byte[] dataBytes = dstStream.toByteArray();
String png_base64 = Base64.getEncoder().encodeToString(dataBytes);//转换成base64串
png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
return "data:image/jpg;base64," + png_base64;
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
if(dstStream!=null) {
try {
dstStream.close();
} catch (IOException e) {
log.error("文件流程关闭失败!");
}
}
}
}
/**
* 封装 list 数据到 word 模板中(word表格)
*
* @param list 数据
* @param tableName 表格列表变量名称
* @return word表格数据DataTable
*/
private static DataTable fillListData(List<Object> list, String tableName) throws Exception {
//创建DataTable,并绑定字段
DataTable dataTable = new DataTable(tableName);
if (list == null || list.size() == 0) {
return dataTable;
}
Class<?> objClass = list.get(0).getClass();
if(objClass.getName().equals("java.util.HashMap")) {
List<String> keys = new ArrayList<>();
Map<String, ?> map = (Map)list.get(0);
// 遍历keySet,并输出key的值
for(String key : map.keySet()){
keys.add(key);
dataTable.getColumns().add(key);
}
// map直接遍历
for (Object obj : list) {// 两个map
//创建DataRow,封装该行数据
DataRow dataRow = dataTable.newRow();
Map map1 = (Map)obj;
for (int i = 0; i < keys.size(); i++) {
String field = keys.get(i);
dataRow.set(i, map1.get(field));
}
dataTable.getRows().add(dataRow);
}
}else {
Field[] fields = objClass.getDeclaredFields();
// 绑定表头字段
for (int i = 0; i < fields.length; i++) {
dataTable.getColumns().add(fields[i].getName());
}
for (Object obj : list) {
//创建DataRow,封装该行数据
DataRow dataRow = dataTable.newRow();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), objClass);
Method method = pd.getReadMethod();
dataRow.set(i, method.invoke(obj));
}
dataTable.getRows().add(dataRow);
}
}
return dataTable;
}
// 填充docx模板中的变量,转换为图片,base64,直接放入html,发送邮件
方法2:
读取html文件,解析html模板中的变量,替换为值
Map<String, String> params = new HashMap<>();
params.put("userName", userName);
params.put("变量","值");
ExpressionParser parser = new SpelExpressionParser();
TemplateParserContext parserContext = new TemplateParserContext();
String html = parser.parseExpression(content, parserContext).getValue(params, String.class);
html转图片
转base64
/**
* 将html转成base64字节
*
* @param html
* @param width
* @param height
* @param perPixel 缩放
* @return
* @throws Exception
*/
public static String html2ImgBase64(String html, int width, int height, int perPixel) {
byte[] bytes = html.getBytes();
BufferedImage img = null;
try (ByteArrayInputStream bin = new ByteArrayInputStream(bytes)) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(bin);
Java2DRenderer renderer = new Java2DRenderer(document, width, height);
SharedContext sharedContext = renderer.getSharedContext();
// sharedContext.setDotsPerPixel(3);// 周年图片(3)
sharedContext.setDotsPerPixel(perPixel);
sharedContext.setDPI(523);
img = renderer.getImage();
// String imgName = Thread.currentThread().getContextClassLoader().getResource("").getPath() + "test.jpg";
// System.out.println("输出地址:" + imgName);
// ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// ImageIO.write(img, "jpg", new FileOutputStream(imgName));
} catch (IOException e) {
log.error("html转换图片创建字节数组输入流对象异常,e:{}", e);
} catch (ParserConfigurationException e) {
log.error("html转换图片创建DocumentBuilder实例异常,e:{}", e);
} catch (SAXException e) {
log.error("html转换图片DocumentBuilder转换输入流异常,e:{}", e);
}
return bufferedImageToBase64(img);
}
// 直接将base64放入html邮件模板中,发送