Java用freemarker导出Word 文档

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

2.把需要动态修改的内容替换成***,如果有图片,尽量选择较小的图片几十K左右,并调整好位置;

3.另存为,选择保存类型Word 2003 XML 文档(*.xml)【这里说一下为什么用Microsoft Office Word打开且要保存为Word 2003XML,本人亲测,用WPS找不到Word 2003XML选项,如果保存为Word XML,会有兼容问题,避免出现导出的word文档不能用Word 2003打开的问题】;

4.用Firstobject free XML editor打开文件,选择Tools下的Indent【或者按快捷键F8】格式化文件内容。左边是文档结构,右边是文档内容;

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">${image}</w:binData>

注意:“>${image}<”这尖括号中间不能加任何其他的诸如空格,tab,换行等符号。

如果需要循环,则使用:<#list maps as map></#list>  maps是Map<String, Object>中key,值为数组,map为自定义;

7. 标识替换完之后,模板就弄完了,另存为.ftl后缀文件即可。注意:一定不要用word打开ftl模板文件,否则xml内容会发生变化,导致前面的工作白做了。

 

导出到本地:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
 
import freemarker.template.Configuration;
import freemarker.template.Template;
import sun.misc.BASE64Encoder;
 
public class WordTest {
 
    // 此目录路径 要求 完整的路径,并且 windows 不能以 /开头 如 : /c:/xxx/xxx
    static URL      freemarker     = WordTest.class.getClassLoader().getResource("freemarker");
    static String freemarkerPath = freemarker != null ? new File(freemarker.getFile()).getAbsolutePath() : new File("freemarker").getAbsolutePath();
 
    //去除PDF水印文件
    static URL aspose = WordTest.class.getClassLoader().getResource("freemarker");
    static String asposePath = freemarker != null ? new File(freemarker.getFile()).getAbsolutePath() : new File("freemarker").getAbsolutePath();
 
    public static void main(String[] args) {
        WordTest wordTest = new WordTest();
        SimpleDateFormat sdf = new SimpleDateFormat("MMdd");
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy年MM月dd日");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日HH时mm分");
        SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy.MM.dd");
        Date date = new Date();
        // 要填充的数据, 注意map的key要和word中${xxx}的xxx一致
        Map<String, Object> dataMap = new HashMap<String, Object>();
        List<Object> list = new ArrayList<Object>();
        for (int i = 0; i < 10; i++) {
            WordUser word = new WordUser();
            word.setImgEntityId(new Long(i));
            word.setImgEntityName("目标" + i);
            word.setLeftUpLatitude(231.342 + i * 10);
            word.setLeftUpLongitude(234.32425 + i * 10);
            list.add(word);
        }
        dataMap.put("date", sdf.format(date));
        dataMap.put("dateTime", sdf1.format(date));
        dataMap.put("organicName", "国有控股");
        dataMap.put("picCreateTime", sdf1.format(new Date()));
        dataMap.put("picCreateTime2", sdf2.format(new Date()));
        dataMap.put("picCreateTime3", sdf3.format(new Date()));
        dataMap.put("imgTypeName", "E-22战斗机");
        dataMap.put("imgRootName", "无人机");
        dataMap.put("imgEntity", "飞机、战斗机、歼-22、隐形战机");
        dataMap.put("list", list);
 
        dataMap.put("station2", "先空下来");
        dataMap.put("coordinate", "先空下来");
        dataMap.put("thematicWords", "境外低轨侦察卫星");
 
        dataMap.put("imgStr", wordTest.getImageStr2("http://47.93.82.37:8180/1.png"));
        // dataMap.put("imgStr", wordTest.getImageStr("/Users/macbook/Documents/1.png"));
        try {
            wordTest.exportSimpleWord(dataMap);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    public void exportSimpleWord(Map<String, Object> dataMap) throws Exception {
        // Configuration用于读取ftl文件
        Configuration configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
 
        /*
         * 以下是两种指定ftl文件所在目录路径的方式, 注意这两种方式都是 指定ftl文件所在目录的路径,而不是ftl文件的路径
         */
        // 指定路径的第一种方式(根据某个类的相对路径指定)
        // configuration.setClassForTemplateLoading(this.getClass(),"");
 
        // 指定路径的第二种方式,我的路径是C:/a.ftl
        configuration.setDirectoryForTemplateLoading(new File(freemarkerPath));
 
        // 创建临时文件
        // File outFile = File.createTempFile("pattern", ".docx");
 
        // 输出文档路径及名称
        File outFile = new File("/Users/macbook/Documents/test1.doc");
 
        // 以utf-8的编码读取模版ftl文件
        Template t = configuration.getTemplate("test4.ftl", "utf-8");
        Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"), 10240);
        t.process(dataMap, out);
        out.close();
        // 删除临时文件
        // outFile.delete();
 
        // word文档转换成PDF
        String wordPath = "/Users/macbook/Documents/test1.doc";
        doc2pdf(wordPath);
    }
// 获取图片流
    public String getImageStr2(String imgPath) {
        ByteArrayOutputStream data = new ByteArrayOutputStream();
        try {
            URL url = new URL(imgPath);
            byte[] by = new byte[1024];
            // 创建链接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(60 * 1000);
            InputStream is = conn.getInputStream();
            // 将内容读取内存中
            int len = -1;
            while ((len = is.read(by)) != -1) {
                data.write(by, 0, len);
            }
            // 关闭流
            is.close();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data.toByteArray());
    }
 
    // word转PDF
    public void doc2pdf(String wordPath) {
//         if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
//         return;
//         }
        try {
            long old = System.currentTimeMillis();
            File file = new File("/Users/macbook/Documents/test1.pdf"); // 新建一个空白pdf文档
            FileOutputStream os = new FileOutputStream(file);
            Document doc = new Document(wordPath); // Address是将要被转化的word文档
            doc.save(os, SaveFormat.PDF);// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,
                                         // EPUB, XPS, SWF 相互转换
            long now = System.currentTimeMillis();
            System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒"); // 转化用时
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    // 验证License 若不验证则转化出的pdf文档会有水印产生
    public boolean getLicense() {
        boolean result = false;
        try {
            //InputStream is = WordTest.class.getClassLoader().getResourceAsStream("license.xml"); // license.xml应放在..\WebRoot\WEB-INF\classes路径下
            InputStream is = new FileInputStream(asposePath+"/license2.xml");
            License aposeLic = new License();
            aposeLic.setLicense(is);
            result = true;
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
 
}

 

浏览器直接下载(get请求):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@RequestMapping(value="/investigation/exportWord",method = RequestMethod.GET)
    @ResponseBody   
    public void exportWord(HttpServletRequest request, HttpServletResponse response) {
        JSONObject result = new JSONObject();
        Long imgPicId = Long.valueOf(request.getParameter("imgPicId"));
        // 要填充的数据, 注意map的key要和word中${xxx}的xxx一致
        Map<String, Object> dataMap = exportSimpleWordService.exportSimpleWord(imgPicId);
        //获取图片类型名称作为文件名
        String imgTypeName = (String) dataMap.get("imgTypeName");
 
        // Configuration用于读取ftl文件
        Configuration configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
 
        // 指定路径我的路径是C:/a.ftl
        try {
            configuration.setDirectoryForTemplateLoading(new File(freemarkerPath));// 指定ftl所在目录,根据自己的改
            response.setContentType("application/msword");
            response.setHeader("Content-Disposition", "attachment;filename=\"" + new String((imgTypeName+"侦查要报.doc").getBytes("GBK"), "iso8859-1") + "\"");
            response.setCharacterEncoding("utf-8");// 此句非常关键,不然word文档全是乱码
            PrintWriter out = response.getWriter();
            Template t = configuration.getTemplate("investigation.ftl", "utf-8");// 以utf-8的编码读取ftl文件
            t.process(dataMap, out);
            out.close();
        }
        catch (Exception e) {
            logger.error("转换成word文档业务服务异常!", e);
            result.put("respCode", BaseRspConstants.RSP_CODE_FAILUR);
            result.put("respDesc", BaseRspConstants.RSP_DESC_FAILUR);  
        }
 
        // return jsonObject;
    }

 

链接:https://www.cnblogs.com/wylblogs/p/word.html

发表评论