天天看點

Java使用freemarker導出帶圖檔的word文檔

1.用Microsoft Office Word打開word原件;

2.把需要動态修改的内容替換成${XX}的形式,如果有圖檔,盡量選擇較小的圖檔幾十K左右的小圖檔,并調整好位置,占位(小圖檔轉換的base64資料少,便于修改);如下圖

Java使用freemarker導出帶圖檔的word文檔

3.另存為,選擇儲存類型Word 2003 XML 文檔(*.xml)【這裡說一下為什麼用Microsoft Office Word打開且要儲存為Word 2003XML,本人親測,用WPS找不到Word 2003XML選項,如果儲存為Word XML,會有相容問題,避免出現導出的word文檔不能用Word 2003打開的問題】,儲存的檔案名不要是中文

4.用notepad++打開檔案;

5. 将文檔内容中需要動态修改内容的地方,換成freemarker的辨別。其實就是Map<String, Object>中key,如${landName};

6.在加入了圖檔占位的地方,會看到一片base64編碼後的代碼,把base64替換成${image},也就是Map<String, Object>中key,值必須要處理成base64;

  代碼如:<w:binData w:name="wordml://自定義.png" xml:space="preserve">${xx}</w:binData>

  注意:“>${xx}<”這尖括号中間不能加任何其他的諸如空格,tab,換行等符号。

  如果需要循環,則使用:<#list maps as map></#list>  maps是Map<String, Object>中key,值為數組,map為自定義;

Java使用freemarker導出帶圖檔的word文檔

7. 辨別替換完之後,模闆就弄完了,另存為.ftl字尾檔案即可。注意:一定不要用word打開ftl模闆檔案,否則xml内容會發生變化,導緻前面的工作白做了。把最開始得到的doc模闆檔案和ftl檔案放在同一級目錄下

8.代碼部分

pom:

<!--  word導出 -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-scratchpad</artifactId>
    <version>3.8</version>
</dependency>
<!-- 生成圖檔-->
<dependency>
    <groupId>org.jfree</groupId>
    <artifactId>jfreechart</artifactId>
    <version>1.0.19</version>
</dependency>

<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.23</version>
</dependency>
           

工具類:

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

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.HashMap;
import java.util.Map;


public class DoOffice_word_freemarker {


    private Configuration configuration = null;

    public DoOffice_word_freemarker() {
        configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
    }

    public void createDoc(HttpServletRequest request, Map<String, Object> dataMap, String fileName)
            throws IOException {
        // dataMap 要填入模本的資料檔案
        //模闆位址
        String tmpFile = request.getSession().getServletContext().getRealPath("/WEB-INF");
        configuration.setDirectoryForTemplateLoading(new File(tmpFile));
        Template t = configuration.getTemplate("template.ftl");
        // 輸出文檔路徑及名稱
        File outFile = new File(fileName);
        Writer out = null;
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(outFile);
            OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");
            // 這個地方對流的編碼不可或缺,使用main()單獨調用時,應該可以,但是如果是web請求導出時導出後word文檔就會打不開,并且包XML檔案錯誤。主要是編碼格式不正确,無法解析。
            // out = new BufferedWriter(new OutputStreamWriter(new
            // FileOutputStream(outFile)));
            out = new BufferedWriter(oWriter);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }

        try {
            t.process(dataMap, out);
            out.close();
            fos.close();
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // System.out.println("---------------------------");
    }

    // 圖檔處理
    public static String getImageStr() {
        String imgFile = "f:/123.png";
        InputStream is = null;
        byte[] data = null;
        try {
            is = new FileInputStream(imgFile);
            data = new byte[is.available()];
            is.read(data);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);
    }

    public static boolean Base64ToImage(String imgStr,String imgFilePath) {
        // 對位元組數組字元串進行Base64解碼并生成圖檔



        BASE64Decoder decoder = new BASE64Decoder();
        try {
            // Base64解碼
            byte[] b = decoder.decodeBuffer(imgStr);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {// 調整異常資料
                    b[i] += 256;
                }
            }

            OutputStream out = new FileOutputStream("f:/123.png");
            out.write(b);
            out.flush();
            out.close();

            return true;
        } catch (Exception e) {
            return false;
        }

    }
    public static void main(String[] args) throws IOException {

        Base64ToImage("","");
        Map<String, Object> datas = new HashMap<String, Object>();
        datas.put("bianhao", "1232");
        datas.put("dushuyi", "1235");
        datas.put("weizhi", "1423");
        datas.put("tuzhi", "25123");
        datas.put("kongshen", "1我23");
        datas.put("ksshuiwei", "123");
        datas.put("endshuiwei","請問123");
        datas.put("kstime", "123");
        datas.put("endtime", "1啊23");
        datas.put("counttime", "123");
        datas.put("result", "1夫人23");
        datas.put("img", getImageStr().substring(22,getImageStr().length()));
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("photo", getImageStr().substring(22,getImageStr().length()));
        dataMap.put("name", "Blue");
        dataMap.put("gender", "男");
        dataMap.put("birth", "1992-2-2");
        dataMap.put("grade", "1203班");
        dataMap.put("major", "軟體");
        dataMap.put("Id", "201219010110");
        dataMap.put("phone", "123456");
        dataMap.put("roomId", "S-222");
        dataMap.put("zhengzhi", "團員");
        dataMap.put("IdCard", "411322199202022212");
        dataMap.put("address", "河南省鄭州市地球村");
        dataMap.put("parent_phone1", "11111111");
        dataMap.put("parent_phone2", "22222222");
        dataMap.put("gold", "這裡是目标,新學期新氣象,好好學習,天天向上");
        DoOffice_word_freemarker mdoc = new DoOffice_word_freemarker();
        //mdoc.createDoc(datas, "d:/00.docx");
        //System.out.println(getImageStr().substring(22,getImageStr().length()));
    }


}
           

通過圖檔位址擷取圖檔然後轉換成base64格式:

public static String GetImageStrFromUrl(String imgURL) {
        byte[] data = null;
        try {
            // 建立URL
            URL url = new URL(imgURL);
            // 建立連結
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5 * 1000);
            InputStream inStream = conn.getInputStream();
            int count = conn.getContentLength();
            data = new byte[count];
            int readCount = 0;
            while (readCount<count){
                readCount += inStream.read(data,readCount,count-readCount);
            }

            //data = new byte[inStream.available()];
            inStream.read(data);
            inStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 對位元組數組Base64編碼
        BASE64Encoder encoder = new BASE64Encoder();
        // 傳回Base64編碼過的位元組數組字元串
        return encoder.encode(data);
    }
           

主業務代碼:

/**
     * WORD導出
     */
    @RequestMapping(value = "/word", method= RequestMethod.GET)
    @ResponseBody
    public String word(HttpServletRequest request) throws Exception {

        //模闆位址(把最開始得到的doc模闆檔案和ftl檔案放在同一級目錄下)
        String tmpFile = request.getSession().getServletContext().getRealPath("/WEB-INF/template.doc");
        //導出檔案儲存位址/usr/apache-tomcat-7.0.69/webapps/template.doc
        String expFile = "D:/"+ DateUtils.getToday() +".doc";

     
        String daba_points = "JH-05";
        String daba_content = "查xx。";
        String daba_result = getResult("J1H-05");
        String daba_images = FileUtil.GetImageStrFromUrl("圖檔位址");
      

        Map<String, Object> datas = new HashMap<String, Object>();
      
    
        datas.put("daba_points", daba_points);
        datas.put("daba_content", daba_content);
        datas.put("daba_result",daba_result);
        datas.put("daba_images", daba_images);
      



        DoOffice_word_freemarker mdoc = new DoOffice_word_freemarker();
        mdoc.createDoc(request,datas, expFile);


        return daba_images;
    }
           

成果:

Java使用freemarker導出帶圖檔的word文檔

繼續閱讀