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 "";
    }
}


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