Java使用freemarker动态导出word

Java使用freemarker动态导出word

适用于Java项目导出word文件,通过freemarker模板引擎动态填充word模板并导出。

1. 所需依赖

<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.13</version>
</dependency>

2. word模板

模板位置放在resource/ftl下面

<html>
<head>
    <title>Welcome!</title>
</head>
<body>
<h1>Welcome ${user}!</h1>
<p>Your Blog Site:
    <a href="${blog.url}">${blog.name}</a>!

<table border="1">
    <tr>
        <#list headers as header>
            <th>${header}</th>
        </#list>
    </tr>

    <#list fansList as fans>
        <tr>
            <td>${fans.name}</td>
            <td>${fans.gender}</td>
            <td>${fans.age}</td>
        </tr>
    </#list>
</table>
</body>

</html>

3. 工具类

import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * @author zxg
 * @date Created in 2022/02/08 17:19
 * Description 文档导出工具类
 */
@Component
@Slf4j
public class DocumentHandler {

    public  void createDoc(Map<String,Object> dataMap, String fileName)  {
        Configuration configuration = new Configuration();
        configuration.setDefaultEncoding("UTF-8");

        //dataMap 要填入模本的数据文件
        //这里我们的模板是放在/resource/ftl包下面
        configuration.setClassForTemplateLoading(this.getClass(), "/ftl");
        Template t=null;
        try {
            //test.ftl为要装载的模板
            t = configuration.getTemplate("test.ftl");
        } catch (IOException e) {
           log.error("load template error, err: <{}>",e.getMessage(),e);
        }
        //输出文档路径及名称
        File outFile = new File(fileName);
        Writer out = null;

        try(FileOutputStream fos = new FileOutputStream(outFile)) {

            OutputStreamWriter oWriter = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
            out = new BufferedWriter(oWriter);
            t.process(dataMap, out);
        } catch (Exception  e) {
            log.error("export word error,err: <{}>",e.getMessage(),e);
        }

        try {
            if(out!=null){
                out.close();
            }
        } catch (IOException e) {
            log.error("error: {}",e.getMessage(),e);
        }
    }
}

业务代码

@RestController
@RequestMapping("/export")
public class ExportController {

    @Autowired
    private ExportService exportService;

    @PostMapping("/word")
    public void auditReport(HttpServletResponse response) {
        exportService.exportAuditReport(response);
    }
}
import com.study.exportword.util.DocumentHandler;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author zxg
 * @date Created in 2022/02/08 17:16
 * Description 导出word文件
 */
@Service
@Slf4j
public class ExportService {

    @Data
    @Builder
    public static class User {
        private String name;
        private String gender;
        private int age;
    }

    @Autowired
    private DocumentHandler documentHandler;

    public void exportAuditReport(HttpServletResponse response) {
        // dataMap未模板填充的数据
        HashMap<String, Object> dataMap = new HashMap<>();
        generateDataMap(dataMap);

        String tmpFile = "C:\\Users\\lenovo\\Desktop\\test.docx";

        documentHandler.createDoc(dataMap, tmpFile);
        File file = new File(tmpFile);
        //文件名编码
        String fileName = file.getName();
        log.info("download file: {}", fileName);
        try {
            fileName = URLEncoder.encode(fileName, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error("file download error, error msg <{}>", e.getMessage(), e);
        }

        //输出流
        try (FileInputStream fis = new FileInputStream(file);
             BufferedInputStream bis = new BufferedInputStream(fis);
             OutputStream os = response.getOutputStream()) {
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION);
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);
            byte[] buffer = new byte[1024];
            int i = bis.read(buffer);
            while (i != -1) {
                os.write(buffer);
                i = bis.read(buffer);
            }
        } catch (Exception e) {
            log.error("file download error, error msg <{}>", e.getMessage(), e);
        }

    }

    private void generateDataMap(HashMap<String, Object> dataMap) {
        dataMap.put("user", "admin");
        HashMap<String, String> blog = new HashMap<>();
        blog.put("url","http://www.baidu.com");
        blog.put("name","admin的博客");
        dataMap.put("blog", blog);
        dataMap.put("headers", Lists.newArrayList("粉丝姓名", "性别", "年龄"));
        List<User> fansList = Stream.of(
                User.builder().name("张三").gender("男").age(20).build(),
                User.builder().name("李四").gender("女").age(21).build(),
                User.builder().name("王五").gender("男").age(24).build())
                .collect(Collectors.toList());
        dataMap.put("fansList",fansList);
    }
}

4. 运行结果

s

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zxg45

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值