导出Word文档

framework摸版方式

导入依赖

用到一个工具包,你也可用自己的代码实现

<!--framework-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
    <version>last</version>
</dependency>

<!--hutool工具包-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>${hutool.version}</version>
</dependency>

代码

WordUtil.java

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

@Slf4j
public class WordUtils {

    /**
     * 创建word
     * @param path Template下的文件路径
     * @param name 摸版文件名称 不要.ftl
     * @param downloadFileName 下载文件名
     * @param dataMap 磨板填充数据
     * @param response HttpServletResponse
     * @throws IOException
     */
    public static void createDocx(String path, String name,String downloadFileName,Map<String, Object> dataMap, HttpServletResponse response) throws IOException {
        String fileName = URLEncoder.encode(downloadFileName+"_" + DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss") + ".docx", "UTF-8");
        response.setContentType("application/vnd.ms-word;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        WordUtils.createDocx(null, path+"/"+name+".ftl", path+"/"+name+".zip", dataMap, response.getOutputStream());
    }


        /**
         * 图片处理:
         * 需要在document.xml.rels文件中设置每张图片,格式如下:
         * <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.jpeg"/>
         * 在document.xml中可通过Id进行引用
         * r:embed=Id
         * 构建数据(dataMap)传入模板前,需要设置picList,
         * dataMap.put("picList",new ArrayList<Map<String,Object>>())
         * Map中需要含有name:图片名称  code:图片ByteArrayInputStream
         *
         * @param xmlRelsTemplateName  图片资源路径
         * @param documentTemplateName word摸版/.flt
         * @param templateZip          Word的修改后缀 docx->zip
         * @param dataMap              摸版数据、变量
         * @param outputStream         输出流
         */
        public static void createDocx(String xmlRelsTemplateName, String documentTemplateName, String templateZip, Map<String, Object> dataMap, OutputStream outputStream) {
            try (OutputStream os = outputStream; ZipOutputStream zipOut = new ZipOutputStream(os)) {
                ByteArrayInputStream documentXmlRelsInput = null;
                if (StrUtil.isNotBlank(xmlRelsTemplateName)) {
                    //图片配置文件模板
                    documentXmlRelsInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, xmlRelsTemplateName);
                }
                Assert.hasText(documentTemplateName, "内容模板不能为空");
                //内容模板
                ByteArrayInputStream documentInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, documentTemplateName);
                Assert.hasText(templateZip, "初始模板不能为空");
                File docxFile = ResourceUtils.getFile("classpath:templates" + templateZip);
                ZipFile zipFile = new ZipFile(docxFile);
                // 压缩包内容
                Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();

                //开始覆盖文档------------------
                int len = -1;
                byte[] buffer = new byte[1024];
                while (zipEntrys.hasMoreElements()) {
                ZipEntry next = zipEntrys.nextElement();
                InputStream is = zipFile.getInputStream(next);
                if (!next.toString().contains("media")) {
                    zipOut.putNextEntry(new ZipEntry(next.getName()));
                    boolean customWrite = false;
                    if (next.getName().indexOf("document.xml.rels") > 0) {
                        if (documentXmlRelsInput != null) {
                            customWrite = true;
                            while ((len = documentXmlRelsInput.read(buffer)) != -1) {
                                zipOut.write(buffer, 0, len);
                            }
                            documentXmlRelsInput.close();
                        }
                    }
                    if ("word/document.xml".equals(next.getName())) {
                        if (documentInput != null) {
                            customWrite = true;
                            while ((len = documentInput.read(buffer)) != -1) {
                                zipOut.write(buffer, 0, len);
                            }
                            documentInput.close();
                        }
                    }

                    if (!customWrite) {
                        while ((len = is.read(buffer)) != -1) {
                            zipOut.write(buffer, 0, len);
                        }
                        is.close();
                    }
                }
            }
            //写入图片
            List<Map<String, Object>> picList = (List<Map<String, Object>>) dataMap.get("picList");
            if (picList != null && picList.size() > 0) {
                for (Map<String, Object> pic : picList) {
                    ZipEntry next = new ZipEntry("word" + StrPool.SLASH + "media" + StrPool.SLASH + pic.get("name"));
                    zipOut.putNextEntry(new ZipEntry(next.toString()));
                    InputStream in = (ByteArrayInputStream) pic.get("code");
                    while ((len = in.read(buffer)) != -1) {
                        zipOut.write(buffer, 0, len);
                    }
                    in.close();
                }
            }
        } catch (Exception e) {
            log.error("word导出失败:" + e.getMessage());
        }
    }
}

resource目录结构

image

posted @ 2022-09-17 17:44  朱思年  阅读(193)  评论(0编辑  收藏  举报