1. 程式人生 > >Word轉換Html後分頁展示--第一部分

Word轉換Html後分頁展示--第一部分

前言

       Word上傳後轉換為Html的問題已經解決,那麼現在問題來了,如果Word內容較多特別是圖片檔案,在網頁上檢視時,載入會耗時耗流量。解決方案就是分頁載入,類似百度文庫的方式。百度文庫對Word顯示是Html的,網上使用更多的一種解決方案是用Flash控制元件,如FlexPaper。

       現在我們使用Html的分頁方式。在Java中沒有找到現成的方法讀取Word中的分頁資料,生成的Html檔案也沒有對分頁特別標記。最開始的思路是把Html內容全部存到資料庫,分頁讀取,可不知道一次讀取多少,也不能用文字個數劃分,因為Word裡面有空格,字型大小不一樣,還有圖片。靈感來源是在瀏覽器中看生成的Html時,偶然想到的。在瀏覽器裡面Html元素是有畫素高度的,通過每個元素高度來劃分分頁,比如600px高度為一頁內容。也就是說分頁的計算交給瀏覽器去完成,把瀏覽器當做一個服務來用。

步驟

       1. 使用Jacob轉換完Html後,自動呼叫瀏覽器開啟Html檔案

       2. 瀏覽器執行Html裡面的js方法,完成分頁計算,並關閉介面

       3. 儲存每頁內容到資料庫,並提供讀取方法

       4. 生成檢視介面,包含分頁載入方法

環境

       1. Tomcat7,使用Websocket需要用到裡面的tomcat-coyote.jar、catalina.jar

       2. Jdk6.0

       3. 獵豹瀏覽器

實現

       使用Jacob將Word轉換為Html請看之前的文章,現在需要實現的是Html生成後,由瀏覽器自動開啟。方案有兩種,一是定時查詢,當發現有新的Html即Open開啟一個新視窗,路徑由查詢返回;二是用Websocket與服務端建立連線,Html生成後由服務端告知瀏覽器開啟一個新視窗。這裡我使用第二種方式。

先給出Websocket介面上的程式碼


<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML>  
<html> 
<head>  
	<title>WebSocket</title>  
	<style>  
		body {
			padding: 10px;
		}  
		#outputPanel {
			background: #f3f3f3;
			border: 1px solid #666;
			min-height: 400px;
			width: 600px;
		}  
	</style>  
</head>  
<body>  
	<input type="button" id="buttonConnect" value="連線伺服器" />  
	<input type="button" id="buttonClose" value="斷開伺服器" />  
	<br>  
	<div id="outputPanel"></div>  
</body>  
<script type="text/javascript">  
    var infoPanel = document.getElementById('outputPanel'); // 輸出結果面板  
    var connButton = document.getElementById('buttonConnect');// 建立連線按鈕  
    var discButton = document.getElementById('buttonClose');// 斷開連線按鈕  
    // 控制檯輸出物件  
    var console = {log : function(text) {infoPanel.innerHTML += text + "<br>";}};  
    // WebSocket演示物件  
    var demo = {  
        socket : null,  // WebSocket連線物件  
        host : '',      // WebSocket連線 url  
        connect : function() {  // 連線伺服器  
            window.WebSocket = window.WebSocket || window.MozWebSocket;  
            if (!window.WebSocket) {    //檢測瀏覽器支援  
                console.log('瀏覽器不支援Websocket');  
                return;  
            }  
            this.socket = new WebSocket(this.host); // 建立連線並註冊響應函式  
            this.socket.onopen = function(){console.log("websocket開啟");};  
            this.socket.onmessage = function(message) {
            	console.log(message.data);
            	if(message.data.indexOf(".html") > 0){
            		window.open("http://127.0.0.1:8081/wordconvert/"+message.data,
            		'win',"height=600,width=620");
            	}
            };  
            this.socket.onclose = function(){  
                console.log("websocket關閉");  
                demo.socket = null; 
            }; 
        }  
    };  
    // 初始化WebSocket連線 url  
    demo.host=(window.location.protocol == 'http:') ? 'ws://' : 'wss://' ;  
    demo.host += window.location.host + '/wordconvert/websocket/say';  
    connButton.onclick = function() {  
        if (!demo.socket){
        	demo.connect(); 
        }
    };  
    discButton.onclick = function() {  
        if (demo.socket) {
        	demo.socket.close();  
        } 
    };  
</script>
</html>
關鍵地方在第46行,根據返回的messge開啟介面。

後臺用到3個類,分別是WordServlet,前端Websocket是與該類互動的。注意該Servlet是繼承自WebSocketServlet

package com.word.websocket;

import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;

public class WordServlet extends WebSocketServlet{
	
	@Override
	protected StreamInbound createWebSocketInbound(String arg0, HttpServletRequest arg1) {
		return new MessageInBound(arg1.getSession().getId());
	}
	
}
第2個類是MessageInBound,該類是Websocket實際工作的地方,有Open、send等監聽方法

package com.word.websocket;

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.nio.CharBuffer;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WsOutbound;

public class MessageInBound extends StreamInbound{

    private String sessionId = "";  
    
	public String getSessionId() {
		return sessionId;
	}

	public MessageInBound(String _sessionId) {  
        this.sessionId = _sessionId;  
    } 
	
	@Override  
    protected void onTextData(Reader reader) throws IOException {  
        char[] chArr = new char[1024];  
        int len = reader.read(chArr);  
        WebSocketMessageInboundPool.sendMessage(String.copyValueOf(chArr, 0, len));
    }  
  
	private void send(String message) throws IOException {
		getWsOutbound().writeTextMessage(CharBuffer.wrap(message));  
    }
	
    @Override
    protected void onOpen(WsOutbound outbound) {  
        super.onOpen(outbound);
        try {
            send("session id = " + this.sessionId);
        } catch (IOException e) {
            e.printStackTrace();
        }
        WebSocketMessageInboundPool.addMessageInbound(this);
    }
	
    @Override  
    protected void onClose(int status) {  
        super.onClose(status);
        WebSocketMessageInboundPool.removeMessageInbound(this);
    }
    
	@Override
	protected void onBinaryData(InputStream arg0) throws IOException {
	}
}
第3個類是WebSocketMessageInboundPool,該類是一個儲存Websocket的連線池,當前端點選“連線伺服器”時,就會將連線儲存起來,用在Html生成時獲取該連線池裡面連線的物件,向其傳送訊息,以實現推送效果,當然這也是Websocket的本質功能

package com.word.websocket;

import java.io.IOException;
import java.nio.CharBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class WebSocketMessageInboundPool {
	private static final Map<String,MessageInBound > connections = 
		new HashMap<String,MessageInBound>(); 
	
	public static void addMessageInbound(MessageInBound inbound){  
        connections.put(inbound.getSessionId(), inbound);  
    }  
      
    public static void removeMessageInbound(MessageInBound inbound){  
        connections.remove(inbound.getSessionId());  
    }
    
    public static void sendMessage(String message){  
        try {  
            Set<String> keySet = connections.keySet();  
            for (String key : keySet) {  
            	MessageInBound inbound = connections.get(key);  
                if(inbound != null){  
                    inbound.getWsOutbound().writeTextMessage(CharBuffer.wrap(message));  
                }  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}
至此步驟1完成了。