由于工作中涉及到一些复杂格式的文件(doc,xls,pdf等)导出,在网上学习一下poi和freemaker两种方式生成文件。poi对于复杂格式文件的转换代码较为复杂,使用freemarker相对较为方便,下面记录一下freemarker生成简单文件的步骤:
1、在要生成的文件中规划好需要的格式,并另存在.xml文件,查看xml文件无误后修改后缀名为.ftl;
比如将下面Excel文件生成为ftl文件:
Excel文件:
ftl代码(只展示主要部分):
<Worksheet ss:Name="Sheet1">
<Table ss:ExpandedColumnCount="4" ss:ExpandedRowCount="2" x:FullColumns="1"
x:FullRows="1" ss:StyleID="s16" ss:DefaultColumnWidth="52"
ss:DefaultRowHeight="15">
<Row>
<Cell><Data ss:Type="String">姓名</Data></Cell>
<Cell><Data ss:Type="String">年龄</Data></Cell>
<Cell><Data ss:Type="String">性别</Data></Cell>
<Cell><Data ss:Type="String">爱好</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">${userName}</Data></Cell>
<Cell><Data ss:Type="String">${age}</Data></Cell>
<Cell><Data ss:Type="String">${sex}</Data></Cell>
<Cell><Data ss:Type="String">${happies}</Data></Cell>
</Row>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header x:Margin="0.3"/>
<Footer x:Margin="0.3"/>
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
</PageSetup>
<Print>
<ValidPrinterInfo/>
<PaperSizeIndex>9</PaperSizeIndex>
<HorizontalResolution>600</HorizontalResolution>
<VerticalResolution>600</VerticalResolution>
</Print>
<Selected/>
<Panes>
<Pane>
<Number>3</Number>
<ActiveRow>1</ActiveRow>
<ActiveCol>3</ActiveCol>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
需要注意的是ftl中接收数据的格式为${},其中传入的数据可以是Map或者实体类,也可以用list集合包装map或者实体类,这就需要在后端或者ftl中对数据进行处理。
2、建立freemarker工具类;
public class FreeMarkerUtils {
private static Configuration configuration = null;
static{
//创建操作类
configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
//注意后缀是以反斜杠开始;setClassForTemplateLoading:在类路径中读取ftl文件
configuration.setClassForTemplateLoading(FreeMarkerUtils.class, "/ftl");
//设置编码格式
configuration.setDefaultEncoding("utf-8");
}
public static void generateFileFromFtl(String templateName, Map<String, Object> map, String filePath, StringWriter stringWriter){
try (FileWriter fw = new FileWriter(filePath)){
//读取模版
Template template = configuration.getTemplate(templateName);
//对模版进行处理,将传来的map写到文件中
template.process(map, fw);
if (stringWriter != null){
template.process(map, stringWriter);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、传入数据;
这里需要将生成的文件作为附件发送,所以需要写一个对应邮件格式的ftl文件并创建发送邮件的工具类;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试邮件-大嘴巴</title>
</head>
<body>
<h2>工作人员兴趣统计:</h2>
<table border="1" cellspacing="0" align="center">
<tr align="center">
<td>姓名</td>
<td>年龄</td>
<td>性别</td>
<td>爱好</td>
</tr>
<tr align="center">
<td>${userName}</td>
<td>${age}</td>
<td>${sex}</td>
<td>${happies}</td>
</tr>
</table>
</body>
</html>
邮件工具类
//发送邮件的工具类:
public class SendMailUtils{
@Value("${spring.mail.host}")
private String host;
@Value("${spring.mail.port}")
private String port;
@Value("${spring.mail.password}")
private String password;
@Value("${spring.mail.username}")
private String userName;
public void sendEmail(String htmlContent, String fileHtml) throws Exception {
JavaMailSenderImpl sender = new JavaMailSenderImpl();
Properties properties = new Properties();
properties.setProperty("mail.transport.protocol", "smtp");// 连接协议
properties.setProperty("mail.smtp.timeout", "25000");
properties.setProperty("mail.smtp.socketFactory.port", port);
properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.setProperty("mail.debug", "true");
sender.setJavaMailProperties(properties);
sender.setUsername(userName);
sender.setPassword(password);
sender.setHost(host);
sender.setPort(Integer.parseInt(port));
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8");
helper.setFrom(userName);
helper.setSubject("test");
helper.setTo("xxx@yyy.com");
helper.setText(htmlContent);
String s = MimeUtility.encodeText("test");
helper.addAttachment(s + ".html", new File(fileHtml));
sender.send(message);
}
}
配置文件中对邮箱的配置:
spring.mail.host=smtp.qq.com
spring.mail.port=587
spring.mail.username=xxx@qq.com
spring.mail.password=填入授权码
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.ssl.enable=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
进行测试:
Map<String, Object> map = new HashMap<>();
map.put("userName", "大嘴巴");
map.put("age", "XX");
map.put("sex", "男");
map.put("happies","敲代码...");
String excelPath = "E:\usr\local\excel\output.xls";
String htmlPath = "E:\usr\local\html\output.html";
StringWriter str = new StringWriter();
generateFileFromFtl("testHtml.ftl", map, htmlPath, str);
sendEmail.sendEmail(str.toString(), htmlPath);
generateFileFromFtl("testExcel.ftl", map, excelPath, null);