SpringBoot 导出Word文档(doc\docx) Office无法打开,WPS正常等坑

本文介绍了在SpringBoot项目中使用Freemarker模板引擎生成Word(docdocx)文档时遇到的坑,如Office无法打开、WPS正常、图片加载问题及特殊字符处理。解决方案包括正确保存XML格式、处理图片Base64编码、避免字体格式不一致导致的分隔问题,以及转义特殊字符。同时提醒注意doc到docx格式转换的方法。

以下对于生成doc文档来说哒,
对于生成docx请移步https://blog.csdn.net/wantLight/article/details/106105416

首先引入freemarker依赖

<!--引入freemarker 模板依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

示例Controller:

    @RequestMapping(value = "/export", method = RequestMethod.GET)
    public void downloadWord(HttpServletRequest request, HttpServletResponse response) {
        try {

            // 告诉浏览器用什么软件可以打开此文件
            response.setHeader("content-Type", "application/msword");
            // 下载文件的默认名称
            response.setHeader("Content-Disposition", "attachment;filename=xx分析.doc");
            Map<String, Object> dataMap = detailService.showWordDetail();

            //创建配置实例对象
            Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
            //设置编码
            configuration.setDefaultEncoding("UTF-8");
            //加载需要装填的模板
            //configuration.setClassForTemplateLoading(this.getClass(), "/");
            ClassPathResource classPathResource = new ClassPathResource("/files/");
            configuration.setDirectoryForTemplateLoading(classPathResource.getFile());

            //设置对象包装器
            configuration.setObjectWrapper(new DefaultObjectWrapper(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS));

            //设置异常处理器
            configuration.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
            //获取ftl模板对象
            Template template = configuration.getTemplate("template.ftl");
            //输出文档
            StringBuilder fileName = new StringBuilder("啦啦啦啦.doc");

//            if (StringUtils.isNotEmpty(data.getStudentName())) {
//                fileName.append(data.getStudentName()).append("的简历").append(".doc");
//            } else {
//                fileName.append("默认简历").append(".doc");
//            }

            try {
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment;filename="
                        + new String(fileName.toString().getBytes("GBK"), "ISO-8859-1"));
                response.setCharacterEncoding("utf-8");//处理乱码问题
                //生成Word文档
                template.process(dataMap, response.getWriter());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                response.flushBuffer();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

word里面生成图片需要将图片转Base64:

 /**
     * 本地图片转换Base64的方法
     *
     * @param imgPath
     */
    public static String imageToBase64(String imgPath) {
        byte[] data = null;
        // 读取图片字节数组
        try {
            ClassPathResource classPathResource = new ClassPathResource(imgPath);
            InputStream in = classPathResource.getInputStream();
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        // 返回Base64编码过的字节数组字符串
        return encoder.encode(Objects.requireNonNull(data));
    }

我的模板/图片路径都在resources/files下:对应传imgPath = files/图3.jpeg
在这里插入图片描述
需要替换的元素用${xxxxxx}占位符在word里替换了,如果有多条数据则添加<#list userList as user><#list>标签,userList是Map里的key。
注意:符号字体格式一定要保持一致,否则会出现转xml后分隔的问题
在这里插入图片描述
比较好的办法是:doc中先不写变量,将doc转成xml,然后用doc打开这个xml,这时候加变量就好了,${name}就不会被分离了。建议使用notepad++,借助插件可以自动格式化xml文档

注意:使用wps保存xml时要保存xml格式(03版的doc格式),否则会出现office 打不开的情况(或者图片无法加载)

在这里插入图片描述

图片出不来还有可能是w:name的后缀名与实际不符合,加${picStyle}替换后缀名~,还要注意前后标签要顶着你的占位符,不要换行或者有空白!!!
在这里插入图片描述

其它

特殊字符的处理:
ftl模板导出word时,如果填充的字符含有特殊字符< 、>、&,那么导出的word是无法打开的。
转义字符对应的特殊符号:&lt; 对应< , &gt;对应> , &amp;对应&

后记

由于导出的doc格式太旧啦,这里需要将doc换成docx(同样使用freemarker的方式)。见我下一篇博客
https://blog.csdn.net/wantLight/article/details/106105416

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值