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类:
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 + "\"}";
}
}
FileUtils类中的Encrypt类:
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;
}
}
controller层实现对word(模板)的复制和对复制后文件的修改:
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;
}
}
Office 在线
通过模板发布文件
Word 预览 编辑
Excel 预览 编辑
Ppt 预览 编辑
Pdf 预览