freemaker生成word模板的各种坑,包含word打不开、批量添加图片、图片变形等问题总结

最近在使用freemaker做一个word模板,里面包含大量表格、截图、超链接等数据、历时一周多,遇到很多坑,现在想想都后怕,现在简单总结一下,希望给以后的小伙伴提供帮助,少走弯路!

坑一:word打不开

可能原因:

1、往xml文件中添加数据占位时,不细心导致文件中出现多余的{、}、;、#等字符,导致xml校验错误,会导致生成的word打不开。

2、word中有超链接,链接中包含多个参数时,会用&进行连接,然而在xml中&属于特殊字符,如若不处理,导致xml校验错误,会导致生成的word打不开;处理方式有两种如下

第一种:使用CDATA包含此链接,使得xml不解析,比如

第二种:将特殊字符转义,&对应的转义为&    其他特殊字符转义可自行去网上查询,转义后的链接就变成www.test.com?param=1&num=2,这种xml是可以解析的。

3、xml校验没有问题(xml校验器https://www.runoob.com/xml/xml-validator.html),此时生成的docx文档,使用wps是可以打开的,但是使用office确打不开,解决方案是直接生成doc格式的文档,这样wps跟office都能打开了,具体原因不详,可能跟freemarker对docx跟doc支持不一样。

坑二:批量添加图片

由于第一次往word文档中加图片,而且是动态批量添加,没有头绪,网上查询了资料也都没有太好的方法,后面想着直接动态循环生成rId,没成想直接成功了,非常开心,但也产生一个新问题,就是图片变形了(下面在详细说),实现方式如下:

往word中加图片,首先在模板中需要插入一个图片进行占位,转换成xml后,关于图片的地方有三点,我自己理解的,描述的可能不太对,见谅!

1、图片的源定义

2、图片的base64码,用变量替换

                                                                           
    ${img_gqctt!"--"}

3、图片展示


    
        
        
        
        
            
            
        
    
    
        
            
            
            
            
        
        
            
                
                
                
                
                    
                    
                    
                        
                            
                                
                                    
                                    
                                        
                                    
                                
                                
                                    
                                    
                                        
                                    
                                
                                
                                    
                                        
                                        
                                    
                                    
                                        
                                    
                                
                            
                        
                    
                
            
        
        
            
                
                
            
            
        
    

1跟2是通过image99.jpeg关联,1跟3是通过rId99关联

具体实现方式:

<#list img_glrcyry as glrcyry>
    

为什么要+200,是为了防止id重复,我这文档中包含大量的图片

<#list img_glrcyry as glrcyry>
	
		${glrcyry.img_glrcyry}
	
<#list img_glrcyry as glrcyry>

    
        
        
        
        
            
            
        
    
    
        
            
        
        
        
            
                
                
                
                
                    
                    
                    
                        
                            
                                
                                    
                                    
                                        
                                    
                                
                                
                                    
                                        
                                            
                                                
                                                
                                            
                                        
                                        
                                        
                                            
                                        
                                    
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                        
                                        
                                        
                                            
                                        
                                    
                                
                            
                        
                    
                
            
            
                
                    
                    
                
                
            
        

这样就能将图片批量动态的添加到word模板中了。

坑三:图片变形问题

因为事先用了一个图片进行占位,所有在模板中,图片的大小固定,如果新插入的图片跟占位大小不一样,就会导致图片变形,压缩或者拉伸。下面看一下图片位置里面代码有两个核心的地方:

第一个是图片在word中的区域,长跟宽的大小,第二个是图片本身的通过像素值转换的长跟宽(我自己理解的,可能描述的不太对),网上有说图片像素值转换成这个大小的计算逻辑,是 像素值*914400/100,然后去替换长跟宽,后面我经过反复试验验证,发现不是很准确,这样会导致图片变形。

我的思路:图片变形无非就是长宽比例不一致导致,所以我们根据要插入的图片的宽跟高,计算宽高比,来改变模板里这个宽高值,保证图片在模板里跟原图是同样的宽高比,这样图片就不会变形。

因为一个图片在word中只能占一页,而实际上有的图片过长,有的图片过宽,所以我的思路是,如果图片过长,就固定长度,压缩宽度,如果图片过宽,就固定宽度,压缩长度。我自己在word中用一个图片拉满,占满一页,宽度大概是5275000,长度大概是8780000,我就以这个为基准,以图片时间宽高计算要在模板中展示的实际宽高,部分代码如下:

BufferedImage bufferedImage = ImgBase64Util.base64String2BufferedImage(imgData);
            double wordProportion = (double) 5275000/8780000;
            double realProportion = (double) bufferedImage.getWidth()/bufferedImage.getHeight();
            // 过宽,以宽度为基准
            if(realProportion >= wordProportion){
                root.put("img_gqctt_width", "5275000");
                long realHeight = 5275000L * bufferedImage.getHeight() / bufferedImage.getWidth();
                root.put("img_gqctt_height", String.valueOf(realHeight));
            }else{
                root.put("img_gqctt_height", "8780000");
                long realWidth = 8780000L * bufferedImage.getWidth() / bufferedImage.getHeight();
                root.put("img_gqctt_width", String.valueOf(realWidth));
            }

这样到时候直接替换模板中的宽高,如果是批量添加图片,需要计算出每个图片的在模板中的实际宽高

至此就能保证图片在word中不变形了!

一周多的时间,中间遇到各种问题,曾一度要奔溃,好在后来慢慢问题全部解决,收获颇丰!继续加油!共勉!

 

写在最后:freemarker对高版本的docx支持不是很好,建议模板生成xml时,选择word 2003 XML文档,不建议选择word XML文档,最后生成word文档时,直接生成doc格式的,能避免很多坑!

freemaker生成word模板的各种坑,包含word打不开、批量添加图片、图片变形等问题总结_第1张图片

你可能感兴趣的:(JAVA,freemarker,图片变形,生成的word打不开)