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的

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
### 回答1: Freemarker可以通过使用Apache POI库来导出图片Word文档。首先,需要在模板中定义一个图片占位符,然后在Java代码中将图片插入到占位符中。具体步骤如下: 1. 在Word模板中定义一个图片占位符,例如:${image}。 2. 在Java代码中,使用Apache POI库加载模板文件,并获取到模板中的图片占位符。 3. 使用POI的XWPFRun类创建一个新的段落,并将图片插入到段落中。 4. 将段落插入到模板中的图片占位符位置。 5. 保存生成Word文档。 示例代码如下: ``` // 加载模板文件 FileInputStream fis = new FileInputStream("template.docx"); XWPFDocument doc = new XWPFDocument(fis); // 获取图片占位符 XWPFParagraph imagePlaceholder = doc.getParagraphs().stream() .filter(p -> p.getText().contains("${image}")) .findFirst().orElse(null); // 创建新的段落 XWPFParagraph newParagraph = doc.createParagraph(); // 插入图片到段落中 XWPFRun newRun = newParagraph.createRun(); newRun.addPicture(new FileInputStream("image.jpg"), XWPFDocument.PICTURE_TYPE_JPEG, "image.jpg", Units.toEMU(200), Units.toEMU(200)); // 将段落插入到图片占位符位置 int index = doc.getPosOfParagraph(imagePlaceholder); doc.removeBodyElement(index); doc.setParagraph(newParagraph, index); // 保存生成Word文档 FileOutputStream fos = new FileOutputStream("output.docx"); doc.write(fos); fos.close(); ``` 注意:在使用POI插入图片时,需要指定图片的类型和大小。示例代码中使用的图片类型为JPEG,大小为200x200像素。 ### 回答2: Freemarker是一种模板引擎,可以将数据和模板结合生成静态文本,并且常见在Spring框架中使用。而导出Word图片,一般需要通过POI或者Apache POI来实现,具体步骤如下: 1.首先需要引入POI和Freemarker的jar包。 2.在模板中添加图片的占位符,例如${logo}。 3.通过Java代码将图片读入到输出流中,然后在模板中替换${logo}的内容为图片字节数组的Base64编码。 4.通过Freemarker将数据和模板结合,生成Word文件。 5.最后需要使用POI将Word文件的后缀名由.ftl改为.doc或.docx,并且编写下载逻辑进行下载。 需要注意的是,在将图片插入Word文档时,可能出现图片比例失调或者无法插入图片的情况,这时需要调整插入图片的方式,可以将图片插入一个模板中,然后将模板插入到Word文档中,以保证插入的图片比例正确。 ### 回答3: FreeMarker是一种Java模板引擎,它允许使用模板生成文本输出,其中包括MS Word文档。在导出word图片时,需要使用FreeMarker的JDBC模式来检索数据和图片,然后将它们插入Word文档中。以下是导出Word图片的步骤: 1.准备Word模板:首先需要创建一个Word模板包含需要添加文本的区域和占位符来插入图片。这可以通过在Word中创建一个新文档,添加文本和占位符,然后保存为docx文件来完成。 2.准备模板数据:使用Java代码从数据库中检索需要导出的数据和图片,并将它们作为数据模型引入FreeMarker模板引擎中。 3.将数据模型应用于模板:使用FreeMarker模板引擎将数据模型应用于Word模板中,并生成将要输出的Word文档。 4.插入图片:通过在FreeMarker模板中使用图片占位符,将图片插入到生成Word文档中。这可以通过将图片从数据库中检索出来并使用二进制方式插入模板中来完成。 5.保存Word文档:完成所有文本和图片的插入后,将生成Word文档保存到文件系统或输出流中即可。 在使用FreeMarker导出Word图片时,需要注意以下几点: 1.在Word模板中应该包含正确的占位符并设置样式和布局。 2.从数据库中检索图片时应该压缩和缩放图片以确保它们适合文档中的区域。 3.在插入图片时,正确处理可能出现的图片格式和分辨率问题。 4.应对可能出现的异常情况进行处理,以确保生成Word文档具有良好的稳定性和可靠性。 总之,使用FreeMarker导出Word图片是一项需要谨慎处理的复杂任务。通过遵循以上步骤和注意事项,可以生成具有高质量和稳健性的Word文档并满足客户的需求。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

符华-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值