用freemarker导出word,带echart图,并弹出下载弹框

HTML转word主要用freemarker模板来处理,如果只是导出文字内容,那很好处理。但是带图片了就比较麻烦。
步骤大概是:在前台,我们把echart图转为base64形式传到后台(echart图是由canvas写的,所以用canvas的一个方法可以直接将图转为base64,这样的话问题就来了,base64长度很长,我们直接用get方法提交的话参数限制,提交会不成功。可是用post方法必须要有返回值,我们想点击按钮直接弹出下载选择框就成为泡影了,下面是我借鉴别人的一个方法)

前台代码:

$.post("<%=path%>/studentAnalysis/ajaxLessonImg.htm",     //会在下面进行代码演示 {img1:barBase64Info1,img2:barBase64Info2,img3:barBase64Info3,img4:barBase64Info4,img5:barBase64Info5},function(result){
        if(result==""){
            layer.msg("网络链接超时!")   
        }else{
            alert(result);
            return;
            var gradeName=$("#gradeName").val();
            var className=$("#className").val();
            var subjectName=$("#subjectName").val();
            var lessonId=$("#lessonId").val();
            var begintime=$("#begintime").val();
            window.location.href="<%=path%>/studentAnalysis/importLessonWord.htm? //会在下面进行代码演示imgUrl="+result+"&gradeName="+gradeName+"&className="+className+"&subjectName="+subjectName+"&lessonId="+lessonId+"&begintime="+begintime;
        }
  });

//意思是先用post方法提交base64至后台,然后后台把base64转为图片存在指定服务器上,然后将图片名再返回到前台,用post请求的返回处理,再进行get请求,此时get请求带的参数就是图片简短的名称,不会出现参数过长的情况。是不是很明智。
接下来我们来看下

后台的处理代码:

         @RequestMapping("ajaxLessonImg.htm")
         @ResponseBody
         public String ajaxLessonImg(HttpServletRequest request,HttpServletResponse response
                 ) throws Exception{
             Map<String,Object>map=new LinkedHashMap<>();
             //图片临时存放目录
             String file=System.getProperty("catalina.home")+\\webapps\\PicServer\\tempImg\\;   //图片要存放的路径
             String img1=request.getParameter("img1").toString();
             String img2=request.getParameter("img2").toString();
             String img3=request.getParameter("img3").toString();
             String img4=request.getParameter("img4").toString();
             String img5=request.getParameter("img5").toString();
             String[] imgArray={img1,img2,img3,img4,img5};
             List<String>fileList=new ArrayList<>();
             for(String base64:imgArray){
                 String fileName=ImageUtil.savePictoServer(base64,file); //将base64转为图片的方法
                 fileList.add(fileName);
             }
              return new Gson().toJson(fileList);

         }

上面gson用到的包
这里写图片描述

展示imgutil里如果对base64进行处理解码还原:

/**
     * 将一个base64转换成图片保存在  path文件夹下  ,命名随机
     * @param base64String
     * @param path  是一个文件夹路径
     * @param imgName 图片名字(没有后缀)
     * @throws Exception
     */
    public static String savePictoServer(String base64String,String path)throws Exception{

        BASE64Decoder decoder = new BASE64Decoder();  //此类需引入的jar包
        //要把+在上传时变成的空格再改为+
        base64String = base64String.replaceAll(" ", "+");
        //去掉“data:image/png;base64,”后面才是base64编码,去掉之后才能解析
        base64String = base64String.replace("data:image/png;base64,","");
        //在本地指定位置建立文件夹,path由控制台那边进行定义
        File dir=new File(path);
        if(!dir.exists()){
         dir.mkdirs();
        }
        String uuidImg=UUID.randomUUID().toString()+".png";
        String fileName=path+uuidImg;
        try {  
            byte[] buffer = decoder.decodeBuffer(base64String);  
            OutputStream os = new FileOutputStream(fileName);
            for(int i =0;i<buffer.length;++i){
                if(buffer[i]<0){//调整异常数据
                    buffer[i]+=256;
                }
            }
            os.write(buffer);  
            os.close();  
        } catch (IOException e) {  
            throw new RuntimeException();  
        }  

       return uuidImg;
    }

需要用的base64相关的包:
这里写图片描述

接下来看看最终使用freemarker模板,并弹出下载弹出框的代码:

 @RequestMapping("importLessonWord.htm")
 public void importLessonWord(HttpServletRequest request,HttpServletResponse response,@ModelAttribute("gradeName")String gradeName,@ModelAttribute("className")String className,
        @ModelAttribute("subjectName")String subjectName,@ModelAttribute("lessonId")String lessonId,@ModelAttribute("begintime")String begintime
         ) throws Exception{
     SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd");
     String time=sdf.format(new Date());
     Map<String,Object>map=new LinkedHashMap<>();                            
     String file=System.getProperty("catalina.home")+tempDirectory;
     String imgUrl=request.getParameter("imgUrl").toString();
     final List<String>fileList=new Gson().fromJson(imgUrl, List.class);
      //图片64位数编码(img1,img2,img3,img4,img5)
      int i=1;
      for(String fileName:fileList){
          String imgBase64=ImageUtil.getImageStr(file+fileName); //模板需要传入base64所以又要将图片转为base64,代码如下代码块
          map.put("img"+i,imgBase64);
          i++;
      }
      //开启一个线程删除临时存放的统计图图片
      new Thread(){
          public void run() {
              for(String fileName:fileList){
                  String fileUrl=System.getProperty("catalina.home")+tempDirectory;
                  File file = new File(fileUrl+fileName);
                  if(file.exists()){
                      file.delete();
                  }
              }
            }
      }.start();

        Template dateTmp = getTemplateObject("lesson.ftl",request);
       //文件名称
        String creadeFile  = java.net.URLEncoder.encode("课堂分析报表-" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()), "UTF-8");
        //获取输出字符对象
        PrintWriter pw=response.getWriter();
        // 生成提示信息
        response.setContentType("application/vnd.ms-doc");
        // 设置响应头
        response.setHeader("content-disposition", "attachment;filename="+creadeFile+".doc");
        dateTmp.process(map, pw);
 }

/**
  * 读取图片在本地存储的位置
   * @param imgFile
   * @throws Exception
   */
  public static String getImageStr(String imgFile) {  
         InputStream in = null;  
         byte[] data = null;  
         try {  
             in = new FileInputStream(imgFile);  
             data = new byte[in.available()];  
             in.read(data);  
             in.close();  
         } catch (IOException e) {  
             e.printStackTrace();  
         }  
         BASE64Encoder encoder = new BASE64Encoder();  
         return encoder.encode(data);  
     }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答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文档并满足客户的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值