poi导出word表格、图片、多段等处理

全文介绍

 

poi-tl(poi template language)是Word模板引擎,使用Word模板和数据创建很棒的Word文档 。
常用标签介绍(官网):

1文本:{{var}} 2. 图片:{{@var}}
3表格:{{#var}} 4. 列表:{{*var}}
5区块对:{{?sections}}{{/sections}} 6. 嵌套:{{+var}}


本次制作的Demo,简写代码、多注释,只为容易理解,读者可根据自己需求进行重构代码、优化代码。

1根据{{table}}、[content],实现word表格导出(有模板)

2根据{{?sections}}{{/sections}},多个表格段落进行表格、图片插入

环境配置

<!-- poi-tl -->
<dependency>
   <groupId>com.deepoove</groupId>
   <artifactId>poi-tl</artifactId>
   <version>1.10.0</version>
</dependency>
<!-- 导出图片指定html格式 -->
<dependency>
   <groupId>io.github.draco1023</groupId>
   <artifactId>poi-tl-ext</artifactId>
   <version>0.4.2</version>
</dependency>

1根据{{table}}、[content],实现word表格导出(有模板)

1.1模板

模板在代码中位置

1.2代码实现

//测试类实现

public class ExportWordTest7 {
    @Test
    void exportWord() throws IOException {

        //1 获取模板文件流
        InputStream resourceAsStream = this.getClass().getResourceAsStream("/templates/pmwordBg.docx");

        //2 word数据集合
        Map<String, Object> params = new HashMap<>();
        params.put("workContentss",getDynamicFlag1());

        //3 图片指定插件
        ConfigureBuilder builder = Configure.builder();
        Configure config = builder.build();

        HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();
        config.customPolicy("workContentss", policy);

        //4 word导出
        //本地测试
        String filePath = FileUtil.getProjectPath() + "document" + File.separator + "牧羊人导出实例.docx";
        dynamicExport(params,new File(filePath),resourceAsStream,config,null,false);
        //浏览器文件名称设置
//        String fileName = wordExportPmProtermVo.getProjectName()+"第"+wordExportPmProtermVo.getJournalTerm()+"期" + ".docx";


    }

    /**
     * @param data      填充数据
     * @param filePath  临时路径
     * @param resource  模板路径
     * @param response  通过浏览器下载需要
     * @param isBrowser true-通过浏览器下载  false-下载到临时路径
     */
    public void dynamicExport(Map<String, Object> data, File filePath, InputStream resource, Configure config, HttpServletResponse response, boolean isBrowser){
        try {
            if (Boolean.FALSE.equals(isBrowser)) {//本地
                File parentFile = filePath.getParentFile();
                if (!parentFile.exists()) {
                    parentFile.mkdirs();
                }
                FileOutputStream out = new FileOutputStream(filePath);
                XWPFTemplate.compile(resource, config).render(data).writeAndClose(out);
            } else {//浏览器
                ServletOutputStream out = response.getOutputStream();
                XWPFTemplate.compile(resource, config).render(data).writeAndClose(out);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * @Description: 一、本日主要工作数据整理
     * @Author: syq
     * @Date: 2023/4/6 18:31
     */
    public List<Map<String,Object>> getDynamicFlag1(){
        List<Map<String, Object>> dynamicFlag = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            Map<String, Object> dynamicTableMap = new HashMap<>();
            dynamicTableMap.put("xh", i+1);//序号
            dynamicTableMap.put("workContent", "工作内容");//专业主要工作
            dynamicTableMap.put("professional", "专业");//专业
            dynamicTableMap.put("inspectedBy", "检查人");//检查人
            dynamicFlag.add(dynamicTableMap);
        }
        return dynamicFlag;
    }
}

/**
 * @author: muyangren
 * @Date: 2023/1/14
 * @Description: com.muyangren.utils
 * @Version: 1.0
 */
public class FileUtil {
    /**
     * 创建FileItem
     * @param file
     * @param fieldName
     * @return
     */
    public static MultipartFile createFileItem(File file, String fieldName) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem item = factory.createItem(fieldName, ContentType.MULTIPART_FORM_DATA.toString(), true, file.getName());
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try {
            FileInputStream fis = new FileInputStream(file);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new CommonsMultipartFile(item);
    }
    /**
     * 下载到本地路径
     * @param file
     * @return
     * @throws IOException
     */
    public static File fileDownloadToLocalPath(MultipartFile file) {
        File destFile = null;
        try {
            //获取文件名称
            if (StringUtils.isEmpty(file.getOriginalFilename())){
                throw new ServerException("导入模板失败!");
            }
            String fileName = file.getOriginalFilename();
            //获取文件后缀
            String pref = fileName.lastIndexOf(".") != -1 ? fileName.substring(fileName.lastIndexOf(".") + 1) : null;
            //临时文件
            //临时文件名避免重复
            String uuidFile = UUID.randomUUID().toString().replace("-", "") + "." + pref;
            destFile = new File(FileUtil.getProjectPath() + uuidFile);
            if (!destFile.getParentFile().exists()) {
                destFile.getParentFile().mkdirs();
            }
            file.transferTo(destFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return destFile;
    }

    /**
     * @return 文件路径
     */
    public static String getProjectPath(){
        String os = System.getProperty("os.name").toLowerCase();
        //windows下
        if (os.indexOf("windows")>=0) {
            return "C://temp/";
        }else{
            return "/usr/local/temp/";
        }
    }

1.3效果图

2根据{{?sections}}{{/sections}},多个表格段落进行表格、图片插入

2.1模板

2.2代码实现

package com.muyangren;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.muyangren.enums.StyleEnum;
import com.muyangren.utils.FileUtil;
import com.muyangren.utils.HtmlUtil;
import com.muyangren.vo.Attachment;
import com.muyangren.vo.Attachments;
import org.apache.commons.lang3.StringUtils;
import org.ddr.poi.html.HtmlRenderPolicy;
import org.junit.jupiter.api.Test;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

/**
 * @Author: syq
 * @Description: ${description}
 * @Date: 2023/4/9 14:33
 * @Version: 1.0
 */
public class ExportWordTest8 {
    /**
     * @Description: word按照指定模式进行导出
     * 1 获取模板文件流
     * 2 数据与word锚点匹配
     * 3 图片指定插件
     * 4 word导出
     * @Author: syq
     * @Date: 2023/4/6 17:22
     */
    @Test
    void exportWord() throws IOException {
        //1 获取模板文件流
        InputStream resourceAsStream = this.getClass().getResourceAsStream("/templates/pmwordtest.docx");

        //2 word数据集合
        Map<String, Object> params = new HashMap<>();
        //2.3 数据与word锚点匹配
        params.put("dynamicFlag1",getDynamicFlag1());
        params.put("workTitle","工作概述");

        //3 图片指定插件
        HtmlRenderPolicy htmlRenderPolicy = new HtmlRenderPolicy();
        ConfigureBuilder builder = Configure.builder();
        Configure config = builder.build();
        config.customPolicy("pictureUrl", htmlRenderPolicy);

        //4 word导出
        //本地测试
        String filePath = FileUtil.getProjectPath() + "document" + File.separator + "牧羊人导出实例.docx";
        dynamicExport(params,new File(filePath),resourceAsStream,config,null,false);
        //浏览器文件名称设置
//        String fileName = wordExportPmProtermVo.getProjectName()+"第"+wordExportPmProtermVo.getJournalTerm()+"期" + ".docx";
//        try {
//            response.setHeader("Content-disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
//        } catch (UnsupportedEncodingException e) {
//            e.printStackTrace();
//        }


    }

    /**
     * @param data      填充数据
     * @param filePath  临时路径
     * @param resource  模板路径
     * @param response  通过浏览器下载需要
     * @param isBrowser true-通过浏览器下载  false-下载到临时路径
     */
    public void dynamicExport(Map<String, Object> data, File filePath, InputStream resource, Configure config, HttpServletResponse response, boolean isBrowser){
        try {
            if (Boolean.FALSE.equals(isBrowser)) {//本地
                File parentFile = filePath.getParentFile();
                if (!parentFile.exists()) {
                    parentFile.mkdirs();
                }
                FileOutputStream out = new FileOutputStream(filePath);
                XWPFTemplate.compile(resource, config).render(data).writeAndClose(out);
            } else {//浏览器
                ServletOutputStream out = response.getOutputStream();
                XWPFTemplate.compile(resource, config).render(data).writeAndClose(out);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

    }
    /**
     * @Description: 一、本日主要工作数据整理
     * @Author: syq
     * @Date: 2023/4/6 18:31
     */
    public List<Map<String,Object>> getDynamicFlag1() throws IOException {
        List<Map<String, Object>> dynamicFlag = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            Map<String, Object> dynamicTableMap = new HashMap<>();
            dynamicTableMap.put("xh", i+1);//序号
            dynamicTableMap.put("workContent", "工作内容");//专业主要工作
            dynamicTableMap.put("professional", "专业");//专业
            dynamicTableMap.put("inspectedBy", "检查人");//检查人
            //url方式
//            List<String> list = new ArrayList<>();
//            list.add("https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E5%9B%BE%E7%89%87&hs=0&pn=0&spn=0&di=7207123747399008257&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&ie=utf-8&oe=utf-8&cl=2&lm=-1&cs=1204793430%2C3263400171&os=3423103612%2C2074051226&simid=1204793430%2C3263400171&adpicid=0&lpn=0&ln=30&fr=ala&fm=&sme=&cg=&bdtype=0&oriquery=%E5%9B%BE%E7%89%87&objurl=https%3A%2F%2Fup.deskcity.org%2Fpic_source%2F2f%2Ff4%2F42%2F2ff442798331f6cc6005098766304e39.jpg&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3B1jfhvtpy_z%26e3B562AzdH3F15ogs5w1AzdH3Fdd9m0m-a-axa_z%26e3Bip4s&gsm=&islist=&querylist=&dyTabStr=MCwxLDYsMyw0LDUsMiw3LDgsOQ%3D%3D");
//            dynamicTableMap.put("pictureUrl",dealWithPictureWidthAndHeight(getBase64String(list)));
            //本地方式
            File file = new File("C:/aa.png");
            String baseString = base64String(file);
            baseString = "data:image/jpeg;base64," + baseString;
            String base = "<img src=" + baseString + " style="width:194.1pt;height:126.05pt;"/>" ;
//                    "<img src=" + baseString + " style="width:194.1pt;height:126.05pt;"/>"+
//                    "<img src=" + baseString + " style="width:194.1pt;height:126.05pt;"/>";
//            String base = "<p style="white-space:pre-wrap;"><img src=" + baseString + " style="width:194.1pt;height:126.05pt;"/>";

            dynamicTableMap.put("pictureUrl", dealWithPictureWidthAndHeight(base));//一张或多张图片
            dynamicFlag.add(dynamicTableMap);
        }
        return dynamicFlag;
    }


    public String base64String(File file) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        FileInputStream fileInputStream = new FileInputStream(file);
        byte[] bytes = new byte[1024];
        //用来定义一个准备接收图片总长度的局部变量
        int len;
        //将流的内容读取到bytes中
        while ((len = fileInputStream.read(bytes)) > 0) {
            //将bytes内存中的内容从0开始到总长度输出出去
            out.write(bytes, 0, len);
        }
        //通过util包中的Base64类对字节数组进行base64编码
        return Base64.getEncoder().encodeToString(out.toByteArray());
    }

    /**
     * @Description: 根据url获取图片base64
     * @Author: syq
     * @Date: 2023/4/7 16:37
     */
    public String getBase64String(List<String> listPath){
        String base64String = "";
        for (int i = 0; i < listPath.size(); i++) {
            String address = listPath.get(i);
            if(StringUtils.isNotBlank(address)){
                String get = netSourceToBase64(address, "GET");
                if(StringUtils.isNotBlank(get)){
                    get = "data:image/jpeg;base64," + get;
                    base64String =  base64String + "<img src=" + get + " style="width:194.1pt;height:126.05pt;"/>";
                }
            }
        }
        return base64String;
    }

    public static String netSourceToBase64(String srcUrl, String requestMethod) {
        ByteArrayOutputStream outPut = new ByteArrayOutputStream();
        byte[] data = new byte[1024 * 8];
        try {
            // 创建URL
            URL url = new URL(srcUrl);
            // 创建链接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod(requestMethod);
            conn.setConnectTimeout(10 * 1000);

            if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
                //连接失败/链接失效/文件不存在
                return null;
            }
            InputStream inStream = conn.getInputStream();
            int len = -1;
            while (-1 != (len = inStream.read(data))) {
                outPut.write(data, 0, len);
            }
            inStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        return Base64.getEncoder().encodeToString(outPut.toByteArray());
    }

    /**
     * @Description: 图片处理
     * @Author: syq
     * @Date: 2023/4/7 16:04
     */
    private String dealWithPictureWidthAndHeight(String content) {
        List<HashMap<String, String>> imagesFiles = HtmlUtil.regexMatchWidthAndHeight(content);
        if (imagesFiles.size() > 0) {
            for (HashMap<String, String> imagesFile : imagesFiles) {
                String newFileUrl = imagesFile.get(StyleEnum.NEW_FILE_URL.getValue());
                String fileUrl = imagesFile.get(StyleEnum.FILE_URL.getValue());
                if (newFileUrl != null) {
                    content = content.replace(fileUrl, newFileUrl);
                }
            }
        }
        return content;
    }

}

2.3效果图 

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>