spring mvc 下 word 文档(含图片)导出

最近在处理 word 文档导出工作,整理并总结下。


经过一番百度和亲测,大部分人使用的都是iText,iReport等...当我去尝试用这几种方法的时候,要实现我的需求可以,但是代码量太大了~~~因为我的 word 文档结构比较复杂,内容较多,有点懒得去写。于是我寻求通过jsp 或 javascript 页面的方式导出,这样子格式都直接在web页面上已经编辑好了,不许通过代码再转成word的形式。


javascript 方式的话需要使用到ActiveXObject,这样子对浏览器是有要求的~~直接放弃

通过jsp方式的话,技术难点关键在图片的导出。百度可以知道,把图片转为base64编码直接输出至页面即可,后面就一直往这个方向走,最后结合FreeMarker,实现了需求。


下面给出步骤

  1. 建立 word 文档模板

  2. word 文档另存为 xml 格式

  在这一步,我尝试直接把xml文件放到后台,把图片base64编码通过el表达式直接替换,发现导出word文档打开会发生错误,因此,我再绕一下,把它另存为.ftl freeMarker模板

3. 编辑xml,把变量替换,改为el表达式,如这里把某图片改为el表达式

<pkg:part pkg:name="/word/media/image4.jpeg" pkg:contentType="image/jpeg" pkg:compression="store">
    <pkg:binaryData>${dataPic}</pkg:binaryData>
</pkg:part>

4. 把模板放到项目下,我这里以 /WEB-INF/templates

  因为我结合了spring mvc 去实现,功能,因此我在 applicationContext.xml 中做好freeMarkerConfig配置如:

 

<!-- Freemarker 配置 -->
    <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <property name="templateLoaderPath" value="/WEB-INF/templates/" />
        <property name="defaultEncoding"    value="UTF-8" />
        <property name="freemarkerSettings">
            <props>
                <prop key="template_update_delay">10</prop>
                <prop key="locale">zh_CN</prop>
                <prop key="number_format">0.##########</prop>
                <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
                <prop key="classic_compatible">true</prop>
                <prop key="template_exception_handler">ignore</prop>
            </props>
        </property>
    </bean>

5. 添加解析 freeMarker 的 ViewResolver

<bean id="ftlViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />
        <property name="suffix" value=".ftl" />
        <property name="exposeRequestAttributes" value="true" />
        <property name="exposeSessionAttributes" value="true" />
        <property name="exposeSpringMacroHelpers" value="true" />
        <property name="order" value="0" />
    </bean>

6. 编写 controller

 @RequestMapping(value = "/report")
    public String word(Model model) {
        getResponse().setCharacterEncoding("UTF-8");
        getResponse().setContentType("application/msword");
        getResponse().addHeader("Content-Disposition", "attachment;filename=report.doc");

        // JFreeChart 图片
        model.addAttribute("dataPic", Base64Utils.image2Str(ChartUtils.createLineChart(prepareDataset(), "最近7天血压数据", "时间", "mmHg"), 1200, 800));

        return "report";
    }


这里还提供一下图片转base64的一个工具类

public class Base64Utils {

    private static BASE64Encoder encoder = new BASE64Encoder();

    private Base64Utils() {
    }

    /**
     * 本地图片转 base64 编码输出
     */
    public static String localImage2Str(String imagePath) {
        File imageFile = new File(imagePath);
        if (imageFile.exists() && imageFile.isFile()) {
            try {
                return image2Str(new FileInputStream(imageFile));
            } catch (FileNotFoundException e) {
                // ignore
            }
        }
        return "";
    }

    /**
     * JFreeChart 图表转 base64 编码
     */
    public static String chartImage2Str(JFreeChart chart, int width, int height) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ChartUtilities.writeChartAsJPEG(out, 1.0f, chart, width, height, null);
            out.flush();

            byte[] data = out.toByteArray();
            return image2Str(new ByteArrayInputStream(data));
        } catch (IOException e) {
            // ignore
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                // ignore
            }
        }
        return "";
    }

    /**
     * 网络图片转 base64 编码输出
     */
    public static String webImage2Str(String urlPath) {
        InputStream in = null;
        try {
            URL url = new URL(urlPath);
            URLConnection connection = url.openConnection();
            connection.connect();

            in = connection.getInputStream();
            return image2Str(in);
        } catch (IOException e) {
            // ignore
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
        return "";
    }

    /**
     * 图片输入流转 base 64 编码
     */
    public static String image2Str(InputStream stream) {
        if (stream != null) {
            try {
                byte[] data = new byte[stream.available()];
                int length = stream.read(data);

                if (length > 0) {
                    return encoder.encode(data);
                }
            } catch (IOException e) {
                // ignore
            }
        }
        return "";
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章