Freemarker和aspose导出word和pdf文件–单体导出和循环导出
-
导包
<!--UtilsWord转PDF--> <dependency> <groupId>aspose.words</groupId> <artifactId>aspose-words</artifactId> <version>15.8.0</version> </dependency> <!-- freemarker jar --> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.28</version> </dependency> <dependency> <groupId>org.docx4j</groupId> <artifactId>docx4j-export-fo</artifactId> <version>8.1.1</version> </dependency>
-
制作word模板–单体导出
循环导出
保存xml格式,在桌面修改后缀,改为.ftl文件,将文件放在resources/template目录下
Ctrl+alt+L,格式化文件,找到表格中设定的参数并在每个参数后面添加:!’ ',必须添加非空判断
循环导出------因为导出是表格横向读取,所以找到第二部分中的${id}同样添加非空判断
ftl文件是多个标签包裹,找到第二部分标签,多个单个标签模块,组成第二部分横向循环表格
找到第二部分总标签,添加list循环标签
在第二部分最后也添加结束标签
rlist是这个循环的名字,后续循环要使用,work是别名,给循环中的值都添加别名
这样整个模板就制作完成
接下来导入工具类,WordUtil和PdfUtil,导出项目都是直接引用
WordUtil
public class WordUtil {
private static final String ENCODING = "UTF-8";
/**
* 生成word文档
*
* @param templateName
* @param map
* @return
* @throws IOException
*/
public static File generateWord(String templateName, Map map) throws IOException {
Configuration configuration = getConfiguration();
Template template = configuration.getTemplate(templateName);
File file = createDoc(map, template);
return file;
}
/**
* 导出word文档
*
* @param templateName
* @param map
* @param title
* @param response
* @throws IOException
*/
public static void exportWord(String templateName, Map map, String title, HttpServletResponse response) throws IOException {
Configuration configuration = getConfiguration();
Template template = configuration.getTemplate(templateName);
File file = null;
InputStream fin = null;
ServletOutputStream out = null;
try {
// 调用工具类的createDoc方法生成Word文档
file = createDoc(map, template);
fin = new FileInputStream(file);
response.setCharacterEncoding(ENCODING);
response.setContentType("application/msword;charset=utf-8");
// 设置浏览器以下载的方式处理该文件名
String fileName = title + ".doc";
response.setHeader("Content-Disposition", "attachment;filename="
.concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
out = response.getOutputStream();
byte[] buffer = new byte[512]; // 缓冲区
int bytesToRead = -1;
// 通过循环将读入的Word文件的内容输出到浏览器中
while ((bytesToRead = fin.read(buffer)) != -1) {
out.write(buffer, 0, bytesToRead);
}
} finally {
if (fin != null) {
fin.close();
}
if (out != null) {
out.close();
}
if (file != null) {
file.delete(); // 删除临时文件
}
}
}
private static Configuration getConfiguration() {
Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
configuration.setDefaultEncoding(ENCODING);
configuration.setClassForTemplateLoading(WordUtil.class, "/templates/");
return configuration;
}
private static File createDoc(Map<?, ?> dataMap, Template template) {
String name = "export.doc";
File f = new File(name);
Template t = template;
try {
// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
Writer w = new OutputStreamWriter(new FileOutputStream(f), ENCODING);
t.process(dataMap, w);
w.close();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
return f;
}
}
PdfUtil
public class PdfUtil {
private static final Logger logger = LoggerFactory.getLogger(PdfUtil.class);
public static void covertDocToPdf(File file, String fileName, HttpServletResponse response) {
response.setContentType("application/force-download;charset=utf-8");
try {
if (!isWordLicense()) {
logger.error("License验证不通过");
}
fileName = fileName + ".pdf";
response.setHeader("Content-Disposition", "attachment;filename="
.concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
FileInputStream fileInputStream = new FileInputStream(file);
Document doc = new Document(fileInputStream);
fileInputStream.close();
doc.save(response.getOutputStream(), SaveFormat.PDF);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (file != null) {
file.delete();
}
}
}
public static boolean isWordLicense() {
boolean result = false;
try {
InputStream inputStream = PdfUtil.class.getClassLoader().getResourceAsStream("asp-license/license.xml");
License license = new License();
license.setLicense(inputStream);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
在resources目录下创建asp-license/license.xml,导出Pdf需要验证收费,收费的都懂的,直接粘贴进去
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Words for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>23dcc79f-44ec-4a23-be3a-03c1632404e9</SerialNumber>
</Data>
<Signature>0nRuwNEddXwLfXB7pw66G71MS93gW8mNzJ7vuh3Sf4VAEOBfpxtHLCotymv1PoeukxYe31K441Ivq0Pkvx1yZZG4O1KCv3Omdbs7uqzUB4xXHlOub4VsTODzDJ5MWHqlRCB1HHcGjlyT2sVGiovLt0Grvqw5+QXBuinoBY0suX0=</Signature>
</License>
下来编写代码测试,可以设置传入参数,传1就导出word,不是1就导出pdf,这个具体看业务逻辑
public void exPdf(HttpServletResponse response,Integer id) {
创建map集合
Map<String, Object> map = new HashMap<>();
try {
//循环添加第二部分
List<Map<Object, Object>> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Map<Object, Object> hashMap = new HashMap<>();
hashMap.put("id", i + 1);
hashMap.put("name", "李四");
hashMap.put("age", "12");
hashMap.put("sex", "男");
hashMap.put("hobby", "爱好");
hashMap.put("work", "工作");
hashMap.put("address", "地址");
list.add(hashMap);
}
map.put("rlist", list);//rlist就是模板中给循环部分起得别名
//单独添加第一部分
map.put("name", "李四填表人");
map.put("age", "12");
map.put("sex", "男");
map.put("hobby", "爱好");
map.put("work", "工作");
map.put("address", "地址");
//导出word
if(id == 1){
WordUtil.exportWord("20230911.ftl",map,"填写导出word名称",response);
}else{
//导出pdf
File file = WordUtil.generateWord("20230911.ftl", map);
PdfUtil.covertDocToPdf(file, "填写导出pdf名称", response);
}
} catch (IOException e) {
e.printStackTrace();
}
}