通过freemaker导出word文档SpringBoot+idea,做成浏览器下载

为什么用freemaker呢,因为用freemarker的模板来搞比较方便,比较快捷也让人更好的可以接受

主要还是因为简单,具体的步骤如下

1.首先你要添加freemaker的相关依赖,还需要在配置类application.yml中添加配置

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

  #################################### Freemarker start #################################
  #    设置freemarker
  #设置是否允许HttpServletRequest属性覆盖(隐藏)控制器生成的同名模型属性
  freemarker:
    allow-request-override: false
    #    开发过程建议关闭缓存
    #启用模板缓存
    cache: false
    #检查模板位置是否存在
    check-template-location: false
    #设置编码格式
    charset: UTF-8
    content-type: text/html; charset=utf-8
    #设置是否应该在与模板合并之前将所有请求属性添加到模型中。
    expose-request-attributes: false
    #设置是否在与模板合并之前将所有HttpSession属性添加到模型中。
    expose-session-attributes: false
    #设置是否公开RequestContext供Spring宏库使用,名称为“SpringMacroRequestContext”。
    expose-spring-macro-helpers: false
    #所有视图的RequestContext属性的名称。
    request-context-attribute:
    # 默认后缀就是.ftl
    suffix: .ftl
    template-loader-path: classPath:/code/
    #################################### Freemarker end ###################################

 具体含义请点击这个大佬的链接

springboot集成freemarker 配置application.properties详解 - 冰~橙 - 博客园 (cnblogs.com)

2.你要找到你需要的这个word文档的具体样子

比如,如下图,看着比较简单,没有做表格,但是用到了循环

 比如这就是你的表格,之后你要去数据库中找到其对应的字段经行更改

如下图所示

 之后进行另存,切记这时保存时要改文件格式

 保存完毕之后更改其后缀名为  .ftl 文件

打开之后Ctrl+A   Ctrl+C然后找到xml在线格式化

XML 在线格式化 | 菜鸟工具 ,直接复制上去,点格式化,这样你就得到了一份很整齐的代码,之后打开我们的idea,找到你的项目把他放下在如下图所示的位置上

打开.ftl有的应该会报错,要修改成正确的格式比如

                <w:r>
                    <w:rPr>
                        <w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:fareast="宋体" w:cs="宋体" w:hint="fareast"/>
                        <w:sz w:val="24"/>
                        <w:sz-cs w:val="24"/>
                        <w:lang w:val="EN-US" w:fareast="ZH-CN"/>
                    </w:rPr>
                    <w:t>${name}</w:t>
                </w:r>

 应为加了遍历所以要加一个list,把它加在你遍历表里的第一个之前,结尾加在遍历的最后

Controller

@PostMapping("user/doc")
@ResponseBody
@ApiOperation(value="导出用户doc", httpMethod = "POST",produces="application/json",notes = "导出用户doc")
public ApiResult exportDoc(Integer pid,Integer id) throws IOException {
//这是我自己写的两个查询方法
    List<BulletinDzh> list = bulletinDzhMapper.selectByPid(pid,id);
    Bulletin bulletin = bulletinMapper.findByName(pid);
    Configuration configuration = new Configuration();
    configuration.setDefaultEncoding("utf-8");
//这是模板的位置
    configuration.setClassForTemplateLoading(this.getClass(), "/code");
//这是引用的模板
    Template template = configuration.getTemplate("name.ftl");
//把数据存入到map中,也就是放到了word文档中
    Map<String,Object> dataMap = new HashMap<String,Object>();
    dataMap.put("name",bulletin.getName());
    dataMap.put("newlist",list);
//这是年月日
    Calendar rightNow = Calendar.getInstance();
    Integer year = rightNow.get(Calendar.YEAR);
    Integer month = rightNow.get(Calendar.MONTH)+1; //第一个月从0开始,所以得到月份+1
    Integer day = rightNow.get(Calendar.DAY_OF_MONTH);
    File outFile = new File("文件导出的名字"+ +year+"-"+month+"-"+day+ ".doc");
    Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
    try {
        template.process(dataMap,out);
        out.flush();
        out.close();
    } catch (TemplateException e) {
        e.printStackTrace();
    }
    return ApiResult.ok();
}

 可能会遇到的问题

  •  If you need a particular format only once, use ?string(pattern), like ?string('dd.MM.yyyy HH:mm:ss'), to specify which fields to display
  • 如果出现时间报错问题 如上
  • 把ftl中的
    <w:t>${new.dutyDate}</w:t>
    
  • 改为 ${new.dutyDate?string('yyyy-MM-dd HH:mm:ss')} 就可以了
  • Ftl文件导出为空的解决办法:
  • ${template.headImg}//如果值为空那么页面便会报错
  • ${template.headImg ! "default"}
  • //如果值为空 那么就默认为 ! 感叹号后面引号内的内容 ,切记需要使用双引号

如果你可以通过上面做出导出了,你就直接用下面得代买就好,也就是try后面的,记得要修改文件路径哦,记得看看代码中得注释,有问题可以及时留言

 @SneakyThrows
    @GetMapping("/doc/{id}")
    @ResponseBody
    @SysLog(value = "导出简报信息", type = LogTypeEnum.DOWNLOAD)
    @ApiOperation(value = "导出用户doc", httpMethod = "Get", produces = "application/json", notes = "导出用户doc")
    public void exportDoc(@PathVariable("id") Integer pid,HttpServletResponse response, HttpServletRequest request) {
        //此方法是我自己写的查询方法
        List<BulletinDzh> list = bulletinDzhMapper.selectByPid(pid);
        //此方法是我自己写的查询方法
        String bulletin = bulletinMapper.findByName(pid);
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
        configuration.setDefaultEncoding("utf-8");
        configuration.setClassForTemplateLoading(this.getClass(), "/code");
        Template template = configuration.getTemplate("dzh3.ftl");
        Map<String, Object> dataMap = new HashMap<>(16);
        dataMap.put("name",bulletin);
        dataMap.put("newlist", list);
        Calendar rightNow = Calendar.getInstance();
        int year = rightNow.get(Calendar.YEAR);
        //第一个月从0开始,所以得到月份+1
        int month = rightNow.get(Calendar.MONTH) + 1;
        int day = rightNow.get(Calendar.DAY_OF_MONTH);
        File outFile = new File("简报导出" + +year + "-" + month + "-" + day + ".doc");
        Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8));
        template.process(dataMap, out);
        //以上为导出到服务器

        //但这么说不是很准确

        //以下为做成链接可以在浏览器中下载
        try {
            //关键点,需要获取的文件所在文件系统的目录,定位准确才可以顺利下载文件    
            //部署的服务器地址
            String filePath = "/yjya/" + "简报导出" + year + "-" + month + "-" + day + ".doc";
            File file = new File(filePath);
            String str = "简报导出";
            //创建一个输入流,将读取到的文件保存到输入流
            InputStream fis = new BufferedInputStream(new FileInputStream(filePath));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 重要,设置response的Header
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(str.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1) + year + "-" + month + "-" + day + ".doc");
            response.setHeader("Content-Length", "" + file.length());
            //octet-stream是二进制流传输,当不知文件类型时都可以用此属性
            response.setContentType("application/octet-stream");
            //跨域请求,*代表允许全部类型
            response.setHeader("Access-Control-Allow-Origin", "*");
            //允许请求方式
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            //用来指定本次预检请求的有效期,单位为秒,在此期间不用发出另一条预检请求
            response.setHeader("Access-Control-Max-Age", "3600");
            //请求包含的字段内容,如有多个可用哪个逗号分隔如下
            response.setHeader("Access-Control-Allow-Headers", "content-type,x-requested-with,Authorization, x-ui-request,lang");
            //访问控制允许凭据,true为允许
            response.setHeader("Access-Control-Allow-Credentials", "true");
            //创建一个输出流,用于输出文件
            OutputStream oStream = new BufferedOutputStream(response.getOutputStream());
            //写入输出文件
            oStream.write(buffer);
            oStream.flush();
            oStream.close();
            System.out.println("下载日志文件:" + str + year + "-" + month + "-" + day + ".doc" + "成功");
            out.flush();
            out.close();
        } catch (IOException ioe) {
            ioe.printStackTrace();
            System.out.println("下载日志文件出错,错误原因:" + ioe);
        }
    }

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot + Freemarker 会自动跳转到 login 页的原因可能是因为你的应用程序中使用了 Spring Security,而 Spring Security 会默认开启登录验证功能。 如果你想要禁用 Spring Security 的登录验证功能,可以在 application.properties 或 application.yml 文件中添加以下配置: ``` spring.security.enabled=false ``` 如果你想要保留 Spring Security 的登录验证功能,可以在你的应用程序中添加一个自定义的登录页面,并将 Spring Security 的登录页面指向你的自定义登录页面。你可以按照以下步骤进行操作: 1. 创建一个自定义的登录页面。比如,你可以将登录页面的文件名设置为 "custom-login.html",并将其放置在 "/templates/" 目录下。 ``` <!DOCTYPE html> <html> <head> <title>Login Page</title> </head> <body> <h2>Login Page</h2> <form action="/login" method="POST"> <label for="username">Username:</label> <input type="text" id="username" name="username"><br><br> <label for="password">Password:</label> <input type="password" id="password" name="password"><br><br> <input type="submit" value="Submit"> </form> </body> </html> ``` 2. 创建一个 Spring Security 的配置类,并在配置类中将登录页面指向你的自定义登录页面。 ``` @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/custom-login.html") .permitAll(); } } ``` 这样,当用户访问需要登录验证的页面时,Spring Security 就会自动跳转到你的自定义登录页面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值