1、PageOffice 实现在线 Office
(1)PageOffice 介绍
PageOffice官网,在官网中可以找到各种语言的版本、案例,通过对技术客服的对接,发现PageOffice有两个版本,一种是在浏览器打开一个新的tab,然后显示文档等(兼容性差,不考虑),另一个种是打开插件,在桌面弹出一个窗口,兼容性好一点,但是每次打开一个文档,都会新增加一个窗口,总是需要手动关闭,每个客户端都需要安装PageOffice插件
这里有个小细节,PageOffice不支持国产化,如果项目需要支持国产化,建议使用永中Office
从上图可以看出,PageOffice是直接独立于浏览器之外的一个软件
(2)项目需求对比
接下来继续分析项目需求,首先看这个插件能否满足,我的项目中使用的所有功能都能满足
- 新建文件
- 新建模板文件
- 新建模板文件(带标签替换)
- 编辑文件
- 查询多个文章段落合并为一个文件(数据库多个段落存的是字符串)
- 保存时设置其他参数值
- 多个二进制文件合并未一个文件(多个文件合并)
- 阅读文件(只读模式)
- 下载文件
- 通过代码构建整篇文章
上面的出了最后一点难度大,其他的都是常规操作,通过代码构建整篇文章意思是用代码拼接出一篇800字作文,这样好理解,包括文字段落、换行、加粗、样式、首航缩进等,一篇标准的文件,我的项目实际上是生成1:1的政府红头文件,对文字的要求更是严格
(3)基本整合过程
这里我就不详细写具体怎么整合的了,官方都会提供案例的,我当时用的是PageOffice V4.0官网示例,然后更具下载的包,将相关jar,依赖,配置文件添加好
pageoffice4.6.0.3.jar
是本地jar,添加到lib下
- 修改web.xml 配置文件,具体的更具你自己的版本修改
<!-- PageOffice Begin -->
<servlet>
<servlet-name>poserver</servlet-name>
<servlet-class>com.zhuozhengsoft.pageoffice.poserver.Server</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>poserver</servlet-name>
<url-pattern>/poserver.zz</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>poserver</servlet-name>
<url-pattern>/sealsetup.exe</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>poserver</servlet-name>
<url-pattern>/posetup.exe</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>poserver</servlet-name>
<url-pattern>/pageoffice.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>poserver</servlet-name>
<url-pattern>/jquery.min.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>poserver</servlet-name>
<url-pattern>/pobstyle.css</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>adminseal</servlet-name>
<servlet-class>com.zhuozhengsoft.pageoffice.poserver.AdminSeal</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>adminseal</servlet-name>
<url-pattern>/adminseal.zz</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>adminseal</servlet-name>
<url-pattern>/loginseal.zz</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>adminseal</servlet-name>
<url-pattern>/sealimage.zz</url-pattern>
</servlet-mapping>
<mime-mapping>
<extension>mht</extension>
<mime-type>message/rfc822</mime-type>
</mime-mapping>
<context-param>
<param-name>adminseal-password</param-name>
<param-value>111111</param-value>
</context-param>
<!-- PageOffice End -->
- 引入相应的js文件
<%-- OfficePage --%>
<script type="text/javascript" src="<%=path%>/pageoffice.js" id="po_js_main"></script>
(4)调用逻辑图
(5)实际使用案例
客户端按照要求,下载客户端插件,然后关闭所有的浏览器,再进行安装,安装的版本需要对应服务器中的jar包版本,我的项目使用规模较大,很多的电脑安装插件都出问题了,反正解决的挺慢的
下面以新建一个模板文件为例,然后保存到服务器,首先前端请求后台,新建文件
var param = '?title=' + encodeURI(obj.field.title)
+ '&issueNumber=' + obj.field.issueNumber
+ '&userIds=' + userIds.join(',')
+ '&inviteDate=' + encodeURI(obj.field.inviteDate)
+ '&attachment=' + encodeURI(obj.field.attachment)
+ '&attachmentName=' + encodeURI(obj.field.attachmentName)
+ '&delayTimeLimit=' + encodeURI(obj.field.delayTimeLimit)
+ '&missTimeLimit=' + encodeURI(obj.field.missTimeLimit);
POBrowser.openWindow('<%=path%>/test/addInitStep.action' + param, 'fullscreen=yes;');
编写controller控制层,有基础的同学应该都能读懂
/**
* 添加Word页面
*
* @param entity
* @param request
* @param model
* @return
*/
@GetMapping("addInitStep")
public String addInitStep(InvitedPaperVo entity, HttpServletRequest request, Model model) throws UnsupportedEncodingException {
PageOfficeCtrl poCtrl = new PageOfficeCtrl(request);
poCtrl.setServerPage(request.getContextPath() + "/poserver.zz");
poCtrl.addCustomToolButton("新建模板文件", "Save()", 1);
poCtrl.setCaption("标题");
UserInfoSession ui = (UserInfoSession) SessionUtils.getSessionAttribute(SessionConst.PC_USER_SESSION);
UserInfoVo userInfoVo = userInfoService.getUserInfoById(ui);
WordDocument doc = new WordDocument();
doc.openDataRegion("inviteYear").setValue(entity.getInviteDate().substring(0, 5));
doc.openDataRegion("inviteDate").setValue(DateUtils.dateClearZero(entity.getInviteDate()));
doc.openDataRegion("issueNumber").setValue(String.valueOf(entity.getIssueNumber()));
doc.openDataRegion("content").setValue("");
doc.openDataRegion("phone").setValue(userInfoVo.getOfficeTel() != null ? userInfoVo.getOfficeTel() : "");
doc.openDataRegion("createUserName").setValue(userInfoVo.getName() != null ? userInfoVo.getName() : "");
poCtrl.setWriter(doc);
poCtrl.webOpen(request.getContextPath() + "/office-templates/invited_paper.doc", OpenModeType.docNormalEdit, "tellsea");
String param = "?title=" + java.net.URLEncoder.encode(entity.getTitle(), "UTF-8")
+ "&issueNumber=" + entity.getIssueNumber()
+ "&userIds=" + entity.getUserIds()
+ "&inviteDate=" + java.net.URLEncoder.encode(entity.getInviteDate(), "UTF-8")
+ "&attachment=" + java.net.URLEncoder.encode(entity.getAttachment(), "UTF-8")
+ "&attachmentName=" + java.net.URLEncoder.encode(entity.getAttachmentName(), "UTF-8")
+ "&delayTimeLimit=" + java.net.URLEncoder.encode(entity.getDelayTimeLimit(), "UTF-8")
+ "&missTimeLimit=" + java.net.URLEncoder.encode(entity.getMissTimeLimit(), "UTF-8");
poCtrl.setSaveFilePage(request.getContextPath() + "/invitedPaper/save.action" + param);
model.addAttribute("poCtrl", poCtrl);
return "admin/invited_paper_add_office";
}
controller返回的是一个页面,提供给PageOffice显示,编写页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%String path = request.getContextPath();%>
<!DOCTYPE html>
<html>
<head>
<title>新建模板文件</title>
<%@ include file="./common/head.jsp" %>
</head>
<body>
<%@ include file="./common/js.jsp" %>
<div style="margin:auto; width: 100%; height: calc(100vh - 25px);">
${poCtrl.getHtmlCode("PageOfficeCtrl1")}
</div>
<script type="text/javascript">
function Save() {
document.getElementById("PageOfficeCtrl1").WebSave();
if (document.getElementById("PageOfficeCtrl1").CustomSaveResult == "ok") {
// document.getElementById("PageOfficeCtrl1").Alert('保存成功!');
if (confirm('保存成功,关闭当前窗口?')) {
window.external.close();
}
}
}
</script>
</body>
</html>
然后编写保存请求,从controller中的poCtrl.setSaveFilePage可以得到保存路径
/**
* 保存基本信息
*
* @param invitedPaperVo
* @return
*/
@PostMapping("save")
@ResponseBody
public void save(InvitedPaperVo invitedPaperVo) {
FileSaver fs = new FileSaver(SessionUtils.getRequest(), SessionUtils.getResponse());
invitedPaperVo.setContent(fs.getFileBytes());
invitedPaperService.saveInvitedPaper(invitedPaperVo);
fs.setCustomSaveResult("ok");
fs.close();
}
上面是保存二进制的方法,建议保存文件到服务器,然后将访问路径保存到数据库,具体的可以看官方给的示例