freeMarker导出word带图片

本文介绍如何使用Freemarker和Java进行Word模板的创建与导出,包括maven依赖配置、模板生成工具类的实现、图片转Base64、Word文档下载及导出流程。

1.maven导入需要的jar包

		<!-- 引入freeMarker的依赖包. -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-freemarker</artifactId>
		</dependency>

2.word模板另存为xml格式

3.写word导出工具类,改写模板目录,支持导出zip格式,根据目录得到图片的base64码

package com.zggk.framework.utils;

import freemarker.template.Configuration;
import freemarker.template.Template;
import sun.misc.BASE64Encoder;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.zggk.framework.utils.word.WordHtmlGeneratorHelper;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;



/**
 * 报告生成工具类
 */
public class WordUtils {
   
	private static Configuration configuration = null;
    static {
        configuration = new Configuration();
        configuration.setDefaultEncoding("UTF-8");
        configuration.setClassForTemplateLoading(WordUtils.class,"/static/filetemp/");  
    }

    private WordUtils() {
        throw new AssertionError();
    }


    public static File createDoc( Map<?, ?> dataMap,String ftlFile,String name){
//    	String name = "xxx.doc";
    	File f = new File(name);
        try {
        	Template Template = configuration.getTemplate(ftlFile,"UTF-8");
            Writer w = new OutputStreamWriter(new FileOutputStream(f), "UTF-8");
            Template.process(dataMap, w);
            w.close();
        } catch (Exception ex) {
            ex.printStackTrace(); 
            throw new RuntimeException(ex);
        }
        return f;
    }
    
	public void downloadWord( String process, HttpServletRequest request, HttpServletResponse response,String title,File file){
        
        //响应头的设置
        response.reset();
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        HttpSession session=request.getSession();
        //设置压缩包的名字
        String zipName=title+".zip";
         //解决不同浏览器压缩包名字含有中文时乱码的问题
        try {
            zipName = new String(URLEncoder.encode(zipName, "UTF-8").getBytes(), "ISO-8859-1");
            response.setHeader("Content-Disposition", "attachment;fileName=\"" + zipName + "\"");
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        //设置压缩流:直接写入response,实现边压缩边下载
        ZipOutputStream zipos = null;
        try {
            zipos = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
            //zipos.setEncoding(System.getProperty("sun.jnu.encoding"));//设置文件名编码方式
            zipos.setMethod(ZipOutputStream.DEFLATED); //设置压缩方法 
        } catch (Exception e) {
            e.printStackTrace();
        }
        session.setAttribute(process, "97");
        //循环将文件写入压缩流
        DataOutputStream os = null;
            try {
                //添加ZipEntry,并ZipEntry中写入文件流
                //这里,加上i是防止要下载的文件有重名的导致下载失败
                zipos.putNextEntry(new ZipEntry(title+".doc"));
                os = new DataOutputStream(zipos);
                InputStream is = new FileInputStream(file);
                byte[] b = new byte[100];
                int length = 0;
                session.setAttribute(process, "98");
                while((length = is.read(b))!= -1){
                    os.write(b, 0, length);
                }
                session.setAttribute(process, "99");
                is.close();
                zipos.closeEntry();
            } catch (IOException e) {
                e.printStackTrace();
            } 
            session.setAttribute(process, "100");
            System.out.println("下载完成-----------------");
        
        //关闭流
        try {
            os.flush();
            os.close();
            zipos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }   
        
    }

    
 public static File createDoc( Map<?, ?> dataMap,String ftlFile){
 		File f = new File("xxx.doc");
        try {
        	Template Template = configuration.getTemplate(ftlFile);
            Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
            Template.process(dataMap, w);
            w.close();
        } catch (Exception ex) {
            ex.printStackTrace(); 
            throw new RuntimeException(ex);
        }
        return f;
    }
    
    
    
    public static String getImageBase(String src) {
    	          if(src==null||src==""){
    	             return "";
    	         }
    	         File file = new File(src);      
    	          if(!file.exists()) {
    	              return "";
    	         }
    	         InputStream in = null;
    	         byte[] data = null;  
    	         try {
    	            in = new FileInputStream(file);
    	         } catch (FileNotFoundException e1) {
    	            e1.printStackTrace();
    	         }
    	         try {  
    	             data = new byte[in.available()];  
    	             in.read(data);  
    	             in.close();  
    	         } catch (IOException e) {  
    	           e.printStackTrace();  
    	         } 
    	         BASE64Encoder encoder = new BASE64Encoder();
    	         return encoder.encode(data);
    	     }
    
    
    /**
     * <p>描述:下载word文档的方法</p>
     * @param request
     * @param response
     * @param title
     * @param file
     */
   public static void downloadReport(HttpServletRequest request, HttpServletResponse response, String title,File file,
		   String uid) {
	   HttpSession session=request.getSession();
       InputStream fin = null;
       OutputStream out = null;
       try {
           fin = new FileInputStream(file);
           response.setCharacterEncoding("utf-8");
           response.setContentType("application/msword");
           // 设置浏览器以下载的方式处理该文件名
           String fileName = title + ".doc";
           response.setHeader("Content-Disposition", "attachment;filename="
                   .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));
           out = response.getOutputStream();
           byte[] buffer = new byte[512];  // 缓冲区
           int len = -1;
           // 通过循环将读入的Word文件的内容输出到浏览器中
           while ((len = fin.read(buffer)) != -1) {
               out.write(buffer, 0, len);
           }
       }catch(Exception e) {
    	   e.printStackTrace();
       }finally {
           if (fin != null) {
               try {
				fin.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
           }
           if (out != null) {
               try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
           }
           if (file != null) {
               file.delete(); // 删除临时文件
           }
 //          session.setAttribute(uid, "100");
       }
   }

    // 根据目录得到图片的base64码

	private String getImageBase64(String roadType, String zqCode, String itemOnlyNum) {
		try {
			String picName = roadType+zqCode+itemOnlyNum+".png";
			InputStream in = new FileInputStream(PicUploadUtils.picPath+picName);
			byte[] data = new byte[in.available()];
	        in.read(data);
	        in.close();
	        // 对字节数组Base64编码
	        byte[] encoder = new Base64().encodeBase64(data);
	        // 返回Base64编码过的字节数组字符串
	        return new String(encoder);
		} catch (Exception e) {
			return null;
		}
	}
   
}

 

4.导出controller层

@RequestMapping(value = "/download", produces = "text/html;charset=UTF-8")
	public Object downloadReport(HttpServletRequest request, HttpServletResponse response) throws Exception {
		try {
			String uid = request.getParameter("uid"); 
			String zqCode = request.getParameter("zqCode");     //政区编码
			String roadType = request.getParameter("roadType"); //路线类型
			String ids = request.getParameter("ids");           //条目id
			String zqName = request.getParameter("zqName");           //条目id
			String isEmpty = request.getParameter("isEmpty");           //是否导出空表的标识
			HttpSession session=request.getSession();
			session.setAttribute(uid, "0");
		    File file = printWordService.downloadReport(uid, session, request, response,zqCode,roadType,ids,zqName,isEmpty);
		    session.setAttribute(uid, "70"); HttpHeaders headers = new HttpHeaders();
		    String fileTitle = "公路养护管理规范化检查评分表";
		    if("H".equals(roadType)) {
		    	fileTitle += "(高速公路)";
		    }else {
		    	fileTitle += "(普通公路)";
		    }
			SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
			String nowDate = formatter.format(new Date());
		    fileTitle += "-"+zqName+"-"+nowDate+".doc";
		    String fileName=new String(fileTitle.getBytes("UTF-8"),"iso-8859-1");//涓轰簡瑙e喅涓枃鍚嶇О涔辩爜闂
		    session.setAttribute(uid, "80");
		    headers.setContentDispositionFormData("attachment", fileName);
		    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
		    session.setAttribute(uid, "100");
		    System.out.println("导出完成......"); 
		    return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

5.导出下载模板service层,给map设置模板参数值

/**
	 * @Description 导出下载模板 
	 * @author 巴菲增
	 * @Date 2020年9月4日 上午10:00:02
	 */
	public File downloadReport(String uid, HttpSession session, HttpServletRequest request,
			HttpServletResponse response, String zqCode, String roadType, String ids, String zqName, String isEmpty) {
		try {
			  Map<String,Object> dataMap = new HashMap<String, Object>();
	    	  List<PrintWord> list = new ArrayList<PrintWord>();
			  dataMap.put("imagesBase64String", "");
			  dataMap.put("imagesXmlHrefString", "");
	    	  if("H".equals(roadType)) {
	    		  dataMap.put("roadType", "高速公路");
	    		  list = getHighCheckData(zqCode,ids,isEmpty,dataMap);        //得到高速公路检查记录
	    	  }else {
	    		  dataMap.put("roadType", "普通公路");
	    		  list = getCommonCheckData(zqCode,ids,isEmpty,dataMap);      //得到普通公路检查记录
	    	  }
			  dataMap.put("zqName", zqName);
			  dataMap.put("lists", list);
			  String fileName = "template.xml";
			  if("true".equals(isEmpty)) {           //选中导出空模板,不用填充检查时间、检查得分、检查截图
				  fileName = "empty.xml";  
			  }
			  return WordUtils.createDoc(dataMap,fileName); 
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

6.模板文件,可以xml、ftl结尾都支持

<?xml version="1.0" encoding="utf-8"?>
<?mso-application progid="Word.Document"?>

<w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wsp="http://schemas.microsoft.com/office/word/2003/wordml/sp2" xmlns:sl="http://schemas.microsoft.com/schemaLibrary/2003/core" w:macrosPresent="no" w:embeddedObjPresent="no" w:ocxPresent="no" xml:space="preserve">
  <w:ignoreSubtree w:val="http://schemas.microsoft.com/office/word/2003/wordml/sp2"/>
  <o:DocumentProperties>
    <o:Title>2010年全国干线公路养护管理</o:Title>
    <o:Author>admin</o:Author>
    <o:LastAuthor>1472052711@qq.com</o:LastAuthor>
    <o:Revision>2</o:Revision>
    <o:TotalTime>0</o:TotalTime>
    <o:Created>2020-03-23T06:23:00Z</o:Created>
    <o:LastSaved>2020-03-23T06:23:00Z</o:LastSaved>
    <o:Pages>1</o:Pages>
    <o:Words>74</o:Words>
    <o:Characters>424</o:Characters>
    <o:Company>Microsoft</o:Company>
    <o:Lines>3</o:Lines>
    <o:Paragraphs>1</o:Paragraphs>
    <o:CharactersWithSpaces>497</o:CharactersWithSpaces>
    <o:Version>16</o:Version>
  </o:DocumentProperties>
  <w:fonts>
    <w:defaultFonts w:ascii="Times New Roman" w:fareast="宋体" w:h-ansi="Times New Roman" w:cs="Times New Roman"/>
    <w:font w:name="Times New Roman">
      <w:panose-1 w:val="02020603050405020304"/>
      <w:charset w:val="00"/>
      <w:family w:val="Roman"/>
      <w:pitch w:val="variable"/>
      <w:sig w:usb-0="E0002EFF" w:usb-1="C000785B" w:usb-2="00000009" w:usb-3="00000000" w:csb-0="000001FF" w:csb-1="00000000"/>
    </w:font>
    <w:font w:name="宋体">
      <w:altName w:val="SimSun"/>
      <w:panose-1 w:val="02010600030101010101"/>
      <w:charset w:val="86"/>
      <w:family w:val="auto"/>
      <w:pitch w:val="variable"/>
      <w:sig w:usb-0="00000003" w:usb-1="288F0000" w:usb-2="00000016" w:usb-3="00000000" w:csb-0="00040001" w:csb-1="00000000"/>
    </w:font>
    <w:font w:name="Cambria Math">
      <w:panose-1 w:val="02040503050406030204"/>
      <w:charset w:val="00"/>
      <w:family w:val="Roman"/>
      <w:pitch w:val="variable"/>
      <w:sig w:usb-0="E00006FF" w:usb-1="420024FF" w:usb-2="02000000" w:usb-3="00000000" w:csb-0="0000019F" w:csb-1="00000000"/>
    </w:font>
    <w:font w:name="仿宋_GB2312">
      <w:altName w:val="仿宋"/>
      <w:charset w:val="86"/>
      <w:family w:val="Modern"/>
      <w:pitch w:val="default"/>
      <w:sig w:usb-0="00000001" w:usb-1="080E0000" w:usb-2="00000010" w:usb-3="00000000" w:csb-0="00040000" w:csb-1="00000000"/>
    </w:font>
    <w:font w:name="@宋体">
      <w:panose-1 w:val="02010600030101010101"/>
      <w:charset w:val="86"/>
      <w:family w:val="auto"/>
      <w:pitch w:val="variable"/>
      <w:sig w:usb-0="00000003" w:usb-1="288F0000" w:usb-2="00000016" w:usb-3="00000000" w:csb-0="00040001" w:csb-1="00000000"/>
    </w:font>
    <w:font w:name="@仿宋_GB2312">
      <w:charset w:val="86"/>
      <w:family w:val="Modern"/>
      <w:pitch w:val="default"/>
      <w:sig w:usb-0="00000001" w:usb-1="080E0000" w:usb-2="00000010" w:usb-3="00000000" w:csb-0="00040000" w:csb-1="00000000"/>
    </w:font>
  </w:fonts>
  <w:lists>
    <w:listDef w:listDefId="0">
      <w:lsid w:val="41E40278"/>
      <w:plt w:val="HybridMultilevel"/>
      <w:tmpl w:val="FFFAAECC"/>
      <w:lvl w:ilvl="0" w:tplc="0409000F">
        <w:start w:val="1"/>
        <w:lvlText w:val="%1."/>
        <w:lvlJc w:val="left"/>
        <w:pPr>
          <w:tabs>
            <w:tab w:val="list" w:pos="420"/>
          </w:tabs>
          <w:ind w:left="420" w:hanging="420"/>
        </w:pPr>
      </w:lvl>
      <w:lvl w:ilvl="1" w:tplc="0AA6DFE2">
        <w:start w:val="1"/>
        <w:lvlText w:val="%2."/>
        <w:lvlJc w:val="left"/>
        <w:pPr>
          <w:tabs>
            <w:tab w:val="list" w:pos="840"/>
          </w:tabs>
          <w:ind w:left="840" w:hanging="420"/>
        </w:pPr>
        <w:rPr>
          <w:color w:val="auto"/>
        </w:rPr>
      </w:lvl>
      <w:lvl w:ilvl="2" w:tplc="0409001B" w:tentative="on">
        <w:start w:val="1"/>
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值