freemarker导出word,带表格和多张图片,解决图片重复和变形

Posted 符华-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了freemarker导出word,带表格和多张图片,解决图片重复和变形相关的知识,希望对你有一定的参考价值。

一、引入freemarker依赖

<!--word生成工具类-->
<dependency>
	<groupId>org.freemarker</groupId>
	<artifactId>freemarker</artifactId>
	<version>2.3.24-incubating</version>
</dependency>

二、准备好word模板和wordXML模板

1、word模板

在这里插入图片描述

2、word模板另存为xml格式

在这里插入图片描述

3、打开xml,先进行格式化,这样更好编辑

格式化好后,我们可以查找字段名,进行定位,找到name字段,所在的位置
在这里插入图片描述
刚开始是这样的,但是因为我们的用户表格,肯定不止一个用户,所以我们要修改好xml,添加list,如下:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
设置图片的宽高,防止图片变形,或者图片太大超出word页面
在这里插入图片描述
在这里插入图片描述
改好xml后,我们将xml重命名,将后缀改为 ftl ,我这里是test.ftl
在这里插入图片描述

三、工具类

1、FileUtils

import org.apache.commons.lang3.ArrayUtils;
import org.apache.poi.ss.usermodel.Workbook;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class FileUtils extends org.apache.tomcat.util.http.fileupload.FileUtils {

    /**
     * 将图片内容转换成Base64编码的字符串,并获得图片宽高,进行缩放
     * @param imageFile 图片文件的全路径名称
     * @param flag 判断图片是否是用户头像
     * @return base64字符串和图片宽高
     */
    public static Map<String,String> getImageBase64String(String imageFile,boolean flag) {
        Map<String,String> map = new HashMap<>();
        if (StringUtils.isEmpty(imageFile)) {
            return null;
        }
        File file = new File(imageFile);
        if (!file.exists()) {
            return null;
        }
        InputStream is = null;
        InputStream is1 = null;
        byte[] data = null;
        try {
            is = new FileInputStream(file);
            is1 = new FileInputStream(file);
            data = new byte[is.available()];
            is.read(data);
            //获取图片宽高
            BufferedImage image = ImageIO.read(is1);
            //图片的原始宽高
            int height = image.getHeight();
            int width  = image.getWidth();
            //如果图片是用户头像的话,按照50*50的标准来判断是否要缩小,否则的话按照500*500
            if (flag){
            	//宽或高有一项大于50时,等比缩小
                if (width > 50 || height > 50){
                    int cWidth  = 50;
                    int cHeight  = 50;
                    int showWidth = cWidth;
                    int showHeight = cHeight;
                    //原图宽高太大进行等比缩放
                    if(1.0 * width/height >= 1.0 * cWidth/cHeight){
                        //图片比较宽
                        showHeight = showWidth * height / width;
                    }else {
                        //图片比较长
                        showWidth = showHeight * width / height;
                    }
                    map.put("height",Integer.toString(showHeight));
                    map.put("width",Integer.toString(showWidth));
                }else {
                	//否则使用图片的原始大小
                    map.put("height",Integer.toString(height));
                    map.put("width",Integer.toString(width));
                }
            }else {
                //宽或高大于500时,进行缩放
                if (width > 500 || height > 500){
                    int cWidth  = 500;
                    int cHeight  = 500;
                    int showWidth = cWidth;
                    int showHeight = cHeight;
                    //原图宽高太大进行等比缩放
                    if(1.0 * width/height >= 1.0 * cWidth/cHeight){
                        //图片比较宽
                        showHeight = showWidth * height / width;
                    }else {
                        //图片比较长
                        showWidth = showHeight * width / height;
                    }
                    map.put("height",Integer.toString(showHeight));
                    map.put("width",Integer.toString(showWidth));
                }else {
                    map.put("height",Integer.toString(height));
                    map.put("width",Integer.toString(width));
                }
            }
            is.close();
            is1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        map.put("encode",encoder.encode(data));
        return map;
    }
}

2、WordUtils

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.Version;

import java.io.*;
import java.util.Map;

public class WordUtils {

    /**
     * @param dataMap 导出数据
     * @param templateName 要使用的模板的名称
     * @param path 导出word的路径以及文件名称
     * 通过模板导出word格式文件
     * */
    public void exportWord(Map<String,Object> dataMap,String templateName,String path) throws IOException, TemplateException {
        //Configuration 用于读取ftl文件
        Configuration configuration = new Configuration(new Version("2.3.0"));
        configuration.setDefaultEncoding("utf-8");
        //指定路径(根据某个类的相对路径指定)
        configuration.setClassForTemplateLoading(this.getClass(),"/template");
        //输出文档路径及名称
        File outFile = new File(path);
        //以utf-8的编码读取ftl文件
        Template template = configuration.getTemplate(templateName, "utf-8");
        Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"), 10240);
        template.process(dataMap, out);
        out.close();
    }
}

四、controller测试

@RestController
@EnableTransactionManagement
@RequestMapping("/test")
public class TestController{

    @ResponseBody
    @GetMapping("/exportWord")
    public JSONObject exportWord(HttpServletResponse response){
        try {
        	//这里是直接模拟数据,可以按照自己的实际需求更改
        	
            //需要导出的模板的数据
            Map<String,Object> dataMap = new HashMap<>();
            
        	//用户列表
            List<Map<String,Object>> userList = new ArrayList<>();
            //第一个用户
            Map<String,Object> user1 = new HashMap<>();
            user1.put("name","admin");
            user1.put("phone","12345678910");
            user1.put("email","123@qq.com");
            //用户头像,包括base64字符串、图片宽、图片高
            user1.put("photo",FileUtils.getImageBase64String("E:\\\\document\\\\图片\\\\1.png",true));
            userList.add(user1);

			//第二个用户
            Map<String,Object> user2 = new HashMap<>();
            user2.put("name","藏剑");
            user2.put("phone","13252101111");
            user2.put("email","cj@163.com");
            user2.put("photo",FileUtils.getImageBase64String("E:\\\\document\\\\图片\\\\2.png",true));
            userList.add(user2);

			//第三个用户
            Map<String,Object> user3 = new HashMap<>();
            user3.put("name","霸刀");
            user3.put("phone","15244447777");
            user3.put("email","bd@111.com");
            user3.put("photo",FileUtils.getImageBase64String("E:\\\\document\\\\图片\\\\3.png",true));
            userList.add(user3);

            List<String> picList1 = new ArrayList<>();
            picList1.add("E:\\\\document\\\\图片\\\\儒风.jpg");
            picList1.add("E:\\\\document\\\\图片\\\\雪河.jpg");

            List<String> picList2 = new ArrayList<>();
            picList2.add("E:\\\\document\\\\图片\\\\风雷.jpg");
            picList2.add("E:\\\\document\\\\图片\\\\驰冥.jpg");
            picList2.add("E:\\\\document\\\\图片\\\\破虏.jpg");

            //第一个图片list
            List<Map<String,String>> pictureList1 = new ArrayList<>();
            //第二个图片list
            List<Map<String,String>> pictureList2 = new ArrayList<>();
            
            for (String s : picList1) {
                pictureList1.add(FileUtils.getImageBase64String(s,false));
            }
            for (String s : picList2) {
                pictureList2.add(FileUtils.getImageBase64String(s,false));
            }
            //将处理好的数据,放到模板数据中
            dataMap.put("pictureList1",pictureList1);
            dataMap.put("pictureList2",pictureList2);
            dataMap.put("userList",userList);
            dataMap.put("code","TESTCODE001");
			//获取当前项目根路径下的temp文件夹
            String fullPath = System.getProperty("user.dir")+"/temp";
            File file = new File(fullPath);
            //将文件导出到temp文件夹下,并命名为test.doc
            String wordName = file.getPath()+"/test.doc";
            WordUtils wordUtils = new WordUtils();
            wordUtils.exportWord(dataMap,"test.ftl",wordName);
        } catch (IOException e) {
            e.printStackTrace();
            return failure("导出失败");
        } catch (TemplateException e) {
            e.printStackTrace();
            return failure("导出失败");
        }
        return null;
    }
}

五、效果

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
看下什么时候更新个,word模板转pdf的

以上是关于freemarker导出word,带表格和多张图片,解决图片重复和变形的主要内容,如果未能解决你的问题,请参考以下文章

freemarker导出wordword转pdf,带附件图片等比缩放

freemarker导出wordword转pdf,带附件图片等比缩放

Freemarker在Java中的使用(动态生成多条数据及多张图片)

java用freemarker导出数据到word(含多图片)

使用freemaker 导出word 含多张图片,若无图片则显示文本信息

FreeMark对导出Word中图片的处理