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完成了。