本文是第5篇
(1)概述
https://blog.csdn.net/a897180673/article/details/80548567
(2)域控安装
https://blog.csdn.net/a897180673/article/details/80563296
(3)office online安装
https://blog.csdn.net/a897180673/article/details/80569869
(4)关联配置
https://blog.csdn.net/a897180673/article/details/80623207
所有的软件安装和配置全部ok了,下面就是代码运行了.
1.域控服务器安装java环境
我们的java 代码在域控服务器上面运行,所以要现在域控服务器上面安装java环境,这个就不演示了,网上windows安装java教程一大推
2.启动office Online 服务器场
这里又是一个新名词:服务器场 ,打开安装office Online 的主机
打开powerShell
(1) 输入 Import-Module OfficeWebApps 回车.
(2)运行下列命令部署服务器场:
New-OfficeWebAppsFarm -InternalURL “http://WIN-5LDI2SVJQOJ.test.com” -ExternalUrl “http://192.168.37.138” -AllowHttp –EditingEnabled
–InternalURL内部访问地址,一般是http://office主机名.AD域控地址;
我的officeOnline主机的名字:
–AllowHttp 是否允许http访问;
–ExternalUrl 外部访问地址,一般是服务器的ip地址;
–EditingEnabled 允许编辑office。
输入第二条命令后 等待一会,就会ok,如下图:
这个时候用可以看下有没有启动起来
在office online 的浏览器 输入:http://win-5ldi2svjqoj.test.com/hosting/discovery
得到以下的结果就ok 了
当然通过ip地址访问也是ok,http://192.168.37.138/hosting/discovery
当然这两个地址在域控服务器上面访问 也是ok 的
3.安装好java环境后,启动服务场后,开始上代码
package com.wopihost.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wopihost.entity.FileInfo;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* WOPI HOST
* Created by ethendev on 2017/4/15.
*/
@RestController
@RequestMapping(value="/wopi")
public class WopiHostContrller {
@Value("${file.path}")
private String filePath;
/**
* 获取文件流
* @param name
* @param response
*/
@GetMapping("/files/{name}/contents")
public void getFile(@PathVariable(name = "name") String name, HttpServletResponse response) {
System.out.println("GET获取文件啦!!!!");
InputStream fis = null;
OutputStream toClient = null;
try {
// 文件的路径
String path = filePath + name;
File file = new File(path);
// 取得文件名
String filename = file.getName();
// 以流的形式下载文件
fis = new BufferedInputStream(new FileInputStream(path));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
// 清空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());
toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
toClient.write(buffer);
toClient.flush();
System.out.println("GET获取文件Contents结束!!!!");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
fis.close();
toClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 保存更新文件
* @param name
* @param content
*/
@PostMapping("/files/{name}/contents")
public void postFile(@PathVariable(name = "name") String name, @RequestBody byte[] content) {
System.out.println("POST获取文件Contents啦!!!!");
// 文件的路径
String path = filePath + name;
File file = new File(path);
FileOutputStream fop = null;
try {
if (!file.exists()) {
file.createNewFile();//构建文件
}
fop = new FileOutputStream(file);
fop.write(content);
fop.flush();
System.out.println("POST获取文件结束!!!!");
System.out.println("------------ save file ------------ ");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fop.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 获取文件信息
* @param request
* @param response
* @return
* @throws UnsupportedEncodingException
*/
@GetMapping("/files/{name}")
public void getFileInfo(HttpServletRequest request, HttpServletResponse response) {
System.out.println("获取文件啦!!!!");
String uri = request.getRequestURI();
FileInfo info = new FileInfo();
try {
// 获取文件名, 防止中文文件名乱码
String fileName = URLDecoder.decode(uri.substring(uri.indexOf("wopi/files/") + 11, uri.length()), "UTF-8");
if (fileName != null && fileName.length() > 0) {
System.out.println("文件不为空啊");
File file = new File(filePath + fileName);
if (file.exists()) {
// 取得文件名
info.setBaseFileName(file.getName());
info.setSize(file.length());
info.setOwnerId("admin");
info.setVersion(file.lastModified());
info.setSha256(getHash256(file));
info.setAllowExternalMarketplace(true);
info.setUserCanWrite(true);
info.setSupportsUpdate(true);
info.setSupportsLocks(true);
}
}
ObjectMapper mapper = new ObjectMapper();
String Json = mapper.writeValueAsString(info);
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(Json);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取文件的SHA-256值
* @param file
* @return
*/
public static String getHash256(File file) {
String value = "";
// 获取hash值
try {
byte[] buffer = new byte[1024];
int numRead;
InputStream fis = new FileInputStream(file);
//如果想使用SHA-1或SHA-256,则传入SHA-1,SHA-256
MessageDigest complete = MessageDigest.getInstance("SHA-256");
do {
//从文件读到buffer
numRead = fis.read(buffer);
if (numRead > 0) {
//用读到的字节进行MD5的计算,第二个参数是偏移量
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
fis.close();
value = new String(Base64.encodeBase64(complete.digest()));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return value;
}
}
看过了代码,再来看下,第一篇说到的那个图
从图中可以看到,office online主机一共会回调2次域控主机,分别是 tell me about the file 还有一个是give me the file
这两次回调 分别对应下面两个接口
@GetMapping(“/files/{name}”)
@PostMapping(“/files/{name}/contents”)
代码中,还有一个 @Value(“${file.path}”) 配置
因为 WOPI Server 主机需要把文件传给 WOPI Client 主机,那么问题来了? WOPI Server 从哪里获取文件? 这里我是直接放在WOPI Server 的C盘,这个文件可以放在任何地方,只要WOPI Server可以拿到这个文件就可以,我为了方便直接放在WOPI Server的c盘
用mvn package 把 这个应用打包成war包 上传到域控 服务器上面.
4.运行域控里面的java代码,查看效果
直接在jar 包所在的目录运行cmd:
java -jar wopihost-0.0.1-SNAPSHOT.jar
程序跑起来如图:
我把一个123.docx放到了域控的磁盘里面,怎么才能预览word 文件?
上面说到的地址 http://win-5ldi2svjqoj.test.com/hosting/discovery 在浏览器返回的结果中搜索 word
就可以看到访问的地址
比如我要查看word ,那么主机地址就是:http://win-5ldi2svjqoj.test.com/wv/wordviewerframe.aspx
当然这个还不够
上面说过 office online 主机会 回调 域控的我们写的java 代码,但是office online主机还不知道 域控在哪里 所以在网址后面还要
加点东西
整个地址是这样:http://win-5ldi2svjqoj.test.com/wv/wordviewerframe.aspx?WOPISrc=http://192.168.37.142/wopi/files/123.docx
从这个地址中可以看出,其实是域控主机访问的office online的主机,并在url中带上了域控的主机的地址WOPISrc,这样office Online主机会根据这个地址回调域控主机里面我们写的代码,一共2次,从而进行office 的显示.
把上面的这个地址输入到域控的浏览器中发现,并不能正确的显示,还报错.
5.原因排查
半个月前弄好的时候忘记记录,现在搞突然没有用,一定是有什么细节忘记了,只好开始排查
首先是 http://win-5ldi2svjqoj.test.com/hosting/discovery 访问这个地址的话,浏览器可以正确的返回一些数据,这个说明office online服务场是正确安装的.
然后在域控的主机上面单独的访问我们编写的wopi 的代码
http://127.0.0.1/wopi/files/123.docx/contents
控制台也确实有输出,说明访问到了,但是ie由于安装没有给我们下载文件,但至少说明wopi 的代码是没有问题的.
继续排查,这个时候突然想起一件事情,office online 的主机是会回调 域控的主机的,那么手动的去调用看看
域控的主机ip:192.168.37.142
在office online 的主机里面的浏览器输入
http://192.168.37.142/wopi/files/123.docx
显示的是无法访问网页
这个时候一想,对啊,可能域控主机的防火墙没有关掉,赶紧进入域控的控制面板–>windows防火墙—>启动或关闭windows防火墙,将域防火墙暂时先关掉,点击确定
这个时候再回到域控的主机 ,把上面的那个地址输入按下回车
ok啦,结果成功的显示了,在右上角上面有 在浏览器中编辑,点击看一下.
可以进行编辑.
大吉大利,一切都是ok 的
至此整个office online 的安装部署,java wopi 代码的运行全部ok.可喜可贺.
6.后记
在我一开始准备安装office online 的时候,同事就跟我说要用到2台机器,一台是安装域控,一台是安装office Online主机,
自己也是这么摸索着安装,测试,运行.
后来在真实的项目中的时候,甲方对安全要求比较高,安装域控是要经过审核的,金融行业,对钱比较敏感,不可能随随便便让你去在他们那里安装个域控的.
重新整理下整个安装过程和代码的运行过程,其实整个过程好像和域控也没啥关系,我们的服务都是office online 主机提供的,能不能只安装这一台服务器,不安装域控了 ?
想法:直接在一台主机上面安装office online ,并在office online 主机上面配置服务场,然后在随便的另外一台主机上面运行java 编写的wopi的代码.
结果是不行的,因为在服务场的时候,运行的power shell 代码有两个参数
New-OfficeWebAppsFarm -InternalURL “http://WIN-5LDI2SVJQOJ.test.com” -ExternalUrl “http://192.168.37.138” -AllowHttp –EditingEnabled
一个是 InternalURL ,一个是ExternalUrl
ExternalUrl是office online 的主机的ip地址,这个好说,
但是InternalURL 你怎么搞了?
如果我们的office online 主机不加入域的话,他的计算机名称里面是没有类似xxx.com 这样的东西的,只是简单的一个名字
不死心,继续用这个名字开启服务场试试?
报错信息明确指明:必须将服务器加入到域中
到微软的官方文档 看一看
官方文档也写了office online 必须是域的一部分.看来域控是必须要有的,office online 主机不能脱离 域控单独运行.
那怎么办?甲方不让安装域控,那只有使用甲方的域控了,好在这个是可以的.
方法:
我们只需要把office online添加到甲方的域中就ok,然后甲方自己再把我们的office online主机 添加进管理,和之前的操作是一样的,只不过,域控主机的操作不是我们而已.然后再申请一个机器,在里面跑wopi 代码就ok.
之前做测试WOPI代码的时候,直接在域控上面跑的,现在加入的是甲方的域控,是不能让你在上面跑java 代码的,所以要另外一个机器,在另外一台机器上跑wopi代码
回到自己的测试.
在虚拟机中新建一个主机,ip地址是:192.168.37.135,安装java 环境,把word文件上传到该服务器的c盘,把之前编写的wopi 的代码上传到上面去,并运行.
访问的地址要变化,回调地址从域控的地址,改成新的主机的地址,也就是下面的这个地址:
http://192.168.37.138/wv/wordviewerframe.aspx?WOPISrc=http://192.168.37.135/wopi/files/123.docx
结果是ok 的
其实在整个过程中,域控的唯一作用就是 让office online主机添加进域,并管理了office online主机,只有这样office online 主机的服务才能跑起来,一旦跑起来了,后面的事情也就跟域控的主机没有什么关系了