基於SSM 的 Office 線上編輯
阿新 • • 發佈:2019-01-10
Office線上編輯功能在OA系統中經常被使用。本文主要介紹在SSM框架下利用Java整合Office Online Server 2016 (OOS) 進行office 線上編輯。OOS的環境搭建之前文章有過介紹,在這裡不進行過多的闡述。具體的程式碼實現如下:
Java 實現WOPI協議:
package com.officeonline; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.URLDecoder; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.Filter; import javax.servlet.FilterConfig; /** * Servlet implementation class wopi */ @WebFilter("/wopi/*") public class OfficeFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // System.out.println("許可權"+request.getParameterValues("power")); HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; String power = httpRequest.getParameter("power"); String uri = httpRequest.getRequestURI(); //獲取完整的Url請求路徑 // 解決中文亂碼問題 String fileUri = URLDecoder.decode(uri.substring(uri.indexOf("/wopi/") + 1, uri.length()), "UTF-8"); String filePath = request.getServletContext().getRealPath("/") + fileUri; if (fileUri.endsWith("/contents")) { // GetFile :返回檔案流 filePath = filePath.substring(0, filePath.indexOf("/contents")); String method = httpRequest.getMethod(); if (method.equals("GET")) { getFile(filePath, httpResponse); } if (method.equals("POST")) { postFile(filePath, httpRequest); } } else { // CheckFileInfo :返回json response.setCharacterEncoding("UTF-8"); response.setContentType("application/json;charset=UTF-8"); PrintWriter out = null; try { out = response.getWriter(); out.write(FileUtils.checkFileInfo(filePath, power)); } catch (IOException e) { e.printStackTrace(); } finally { if (out != null) { out.close(); } } } return; } private HttpServletResponse getFile(String path, HttpServletResponse response) { try { // path是指欲下載的檔案的路徑。 File file = new File(path); // 取得檔名。 String filename = file.getName(); String contentType = "application/octet-stream"; // 以流的形式下載檔案。 InputStream fis = new BufferedInputStream(new FileInputStream(path)); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); // 清空response response.reset(); // 設定response的Header response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes("utf-8"), "ISO-8859-1")); response.addHeader("Content-Length", "" + file.length()); OutputStream toClient = new BufferedOutputStream(response.getOutputStream()); response.setContentType(contentType); toClient.write(buffer); toClient.flush(); toClient.close(); } catch (IOException ex) { ex.printStackTrace(); } return response; } public static byte[] getRequestPostBytes(HttpServletRequest request) throws IOException { int contentLength = request.getContentLength(); if (contentLength < 0) { return null; } byte buffer[] = new byte[contentLength]; for (int i = 0; i < contentLength;) { int readlen = request.getInputStream().read(buffer, i, contentLength - i); if (readlen == -1) { break; } i += readlen; } return buffer; } public void postFile(String path, HttpServletRequest request) { // 檔案的路徑 File file = new File(path); try { if (!file.exists()) { file.createNewFile();// 構建檔案 } String submitMehtod = request.getMethod(); if (submitMehtod.equalsIgnoreCase("post")) { byte[] bytes = getRequestPostBytes(request); FileOutputStream fop = new FileOutputStream(file); fop.write(bytes); fop.flush(); fop.close(); } } catch (IOException e) { e.printStackTrace(); } } @Override public void destroy() { // TODO Auto-generated method stub } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }
OfficeFilter 中引用的FileUtils類:
FileUtils類中的Encrypt類:package com.officeonline; import java.io.File; public class FileUtils { /** * 獲取檔案基本資訊 * * @param filePath * 檔案路徑 * @return */ public static String checkFileInfo(String filePath, String power) { File file = new File(filePath); // String hash=null; String baseFileName = null; // 檔名 String ownerId = null; // 檔案所有者的唯一編號 long size = 0; // 檔案大小,以bytes為單位 String sha256 = null; // 檔案的256位bit的SHA-2編碼雜湊內容 long version = 0; // 檔案版本號,檔案如果被編輯,版本號也要跟著改變 boolean Write = false; boolean Print = true; // 在網頁中獲取使用者是否有許可權編輯和列印,根據獲取的引數設定office的功能 if (power == null) { Write = false; Print = true; } else { if (power.equals("write")) { Write = true; } if (power.equals("print")) { Print = false; } if (power.equals("writeprint") || power.equals("printwrite")) { Write = true; Print = false; } } if (file.exists()) { // 取得檔名。 baseFileName = file.getName(); size = file.length(); // 取得檔案的字尾名。 ownerId = "admin"; version = file.lastModified(); sha256 = new Encrypt().SHA256(baseFileName); } return "{\"DisablePrint\":\"" + Print + "\",\"SupportsLocks\":\"" + true + "\",\"Sha256\":\"" + sha256 + "\",\"SupportsUpdate\":\"" + true + "\",\"UserCanWrite\":\"" + Write + "\",\"BaseFileName\":\"" + baseFileName + "\",\"OwnerId\":\"" + ownerId + "\",\"Size\":\"" + size + "\",\"AllowExternalMarketplace\":\"" + true + "\",\"Version\":\"" + version + "\"}"; } }
controller層實現對word(模板)的複製和對複製後文件的修改:package com.officeonline; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class Encrypt { /** * 傳入文字內容,返回 SHA-256 串 * * @param strText * @return */ public String SHA256(final String strText) { return SHA(strText, "SHA-256"); } /** * 傳入文字內容,返回 SHA-512 串 * * @param strText * @return */ public String SHA512(final String strText) { return SHA(strText, "SHA-512"); } /** * 字串 SHA 加密 * * @param strSourceText * @return */ private String SHA(final String strText, final String strType) { // 返回值 String strResult = null; // 是否是有效字串 if (strText != null && strText.length() > 0) { try { // SHA 加密開始 // 建立加密物件 並傳入加密型別 MessageDigest messageDigest = MessageDigest.getInstance(strType); // 傳入要加密的字串 messageDigest.update(strText.getBytes()); // 得到 byte 型別結果 byte byteBuffer[] = messageDigest.digest(); // 將 byte 轉換為 string StringBuffer strHexString = new StringBuffer(); // 遍歷 byte buffer for (int i = 0; i < byteBuffer.length; i++) { String hex = Integer.toHexString(0xff & byteBuffer[i]); if (hex.length() == 1) { strHexString.append('0'); } strHexString.append(hex); } // 得到返回結果 strResult = strHexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } return strResult; } }
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import util.UrlCode;
@Controller
public class OfficeController {
@RequestMapping(value = "/openmodle.do")
@ResponseBody
public String openmodel(HttpServletRequest request, HttpServletResponse response) throws IOException {
String filePath = request.getServletContext().getRealPath("/");
FileInputStream fis = new FileInputStream(filePath + "wopi/files/fs/t1.docx");//t1.docx為模板檔案
FileOutputStream fos = new FileOutputStream(filePath + "wopi/files/fs/t2.docx");//t2.docx為按照末班新建的檔案
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int by = 0;
byte[] buf = new byte[104857600];//預設上傳最大檔案為100M
while ((by = bis.read(buf)) != -1) {
bos.write(buf, 0, by);
}
fis.close();
fos.close();
bis.close();
bos.close();
String Wopisrc=UrlCode.url("http://xx.xx.xx.xx:8080/SmartSchool/wopi/files/fs/t2.docx?power=write");
return "http://xx.xx.xx.xx/we/wordeditorframe.aspx?WOPISrc="+Wopisrc;
}
}
Html頁面的實現:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Office 線上</title>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
function openmodle() {
filename = prompt("請輸入新建檔名:","新建檔案");
if (filename != null){
alert(">>>>>>>>>>>>>>>>>>>>>"+filename+">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
$.ajax({
url : "openmodle.do",
data : JSON.stringify(filename),//使用者新建檔案的檔名傳到前臺
type : "POST",
success : function(msg) {
console.log("成功");
console.log(msg);
window.open(msg);
},
error : function(data, textStatus, errorThrown) {
console.log("失敗");
},
});
}else{
alert("你按了[取消]按鈕");
}
}
</script>
</head>
<body>
<a href="#"onclick="openmodle()">通過模板釋出檔案</a>
<table>
<tr><td>Word<td><td><a href="http://xx.xx.xx.xx/wv/wordviewerframe.aspx?WOPISrc=http%3A%2F%2Fxx.xx.xx.xx%3A8080%2FSmartSchool%2Fwopi%2Ffiles%2F1.docx">預覽</a><td><td><a href="http://xx.xx.xx.xx/we/wordeditorframe.aspx?WOPISrc=http%3A%2F%2Fxx.xx.xx.xx%3A8080%2FSmartSchool%2Fwopi%2Ffiles%2F1.docx%3Fpower%3Dwrite">編輯</a><td></tr>
<tr><td>Excel<td><td><a href="http://xx.xx.xx.xx/x/_layouts/xlviewerinternal.aspx?WOPISrc=http%3A%2F%2Fxx.xx.xx.xx%3A8080%2FSmartSchool%2Fwopi%2Ffiles%2F1.xlsx">預覽</a><td><td><a href="http://xx.xx.xx.xx/x/_layouts/xlviewerinternal.aspx?edit=1&WOPISrc=http%3A%2F%2Fxx.xx.xx.xx%3A8080%2FSmartSchool%2Fwopi%2Ffiles%2F1.xlsx%3Fpower%3Dwrite">編輯</a><td></tr>
<tr><td>Ppt<td><td><a href="http://xx.xx.xx.xx/p/PowerPointFrame.aspx?WOPISrc=http%3A%2F%2Fxx.xx.xx.xx%3A8080%2FSmartSchool%2Fwopi%2Ffiles%2F1.pptx">預覽</a><td><td><a href="http://xx.xx.xx.xx/p/PowerPointFrame.aspx?PowerPointView=EditView&WOPISrc=http%3A%2F%2Fxx.xx.xx.xx%3A8080%2FSmartSchool%2Fwopi%2Ffiles%2F1.pptx%3Fpower%3Dwrite">編輯</a><td></tr>
<tr><td>Pdf<td><td><a href="http://xx.xx.xx.xx/wv/wordviewerframe.aspx?PdfMode=1&WOPISrc=http%3A%2F%2Fxx.xx.xx.xx%3A8080%2FSmartSchool%2Fwopi%2Ffiles%2F1.pdf">預覽</a><td><td></tr>
</table>
</body>
</html>