最近一段时间,在项目中集成了WebOffice2015的插件。有些心得体会,在这里和大家分享一下,不喜勿喷~~~~~~~~
原项目中之前上传和下载附件集成的是WebOffice2003,由于新需求是实现文档(word)的在线编辑功能,所以这里集成WebOffice官网http://www.goldgrid.com/jinge_download/Index.aspx?num=5&firstid=11&flag=0&secondid=67中最新的2015版本的插件。
第一:
去官网下载他们的demo,下载完成之后看到
这里就是所有的文档、文件夹、隐藏目录、文件等
第二:
如果之前开发环境已经集成了2003或者版本比2015低的插件,这里需要更换版本(后面第三点是没有集成过的做法)。具体做法:
2.1 iWebOffice2015.cab 需要放置原先iWebOffice2003.cab(或者iWebOffice2003.ocx控件)作为替代使用。
2.2替换js,将iWebOffice2015.js拷贝到集成代码目录,与原始的
iWebOffice2003.js&iWebOffice2009.js放置在同一目录,将集成控件的代码中调用:
<script src="iWebOffice2003.js"></script>
<script src="iWebOffice2009.js"></script>
更换成:<script src="iWebOffice2015.js"></script>
2.3在DocumentEdit.jsp中增加iWebOffice2015控件OnReady事件,调用代码如下:
<script language="javascript" for=WebOffice2015 event="OnReady()">
//获取iWebOffice2015控件对象,WebOffice.FuncExtModule是iWebOffice2015控件扩展接口对象
WebOffice = document.getElementById("WebOffice2015");
webform.WebOffice = WebOffice.FuncExtModule; //webform.WebOffice是之前03&09控件使用的对象
Load(); //避免页面加载完,控件还没有加载的情况
</script>
2.4 在DocumentEdit.jsp中需要删除OnLoad=”Load()”代码:
<body bgcolor="#ffffff" onLoad="Load()" onUnload="UnLoad()"> <!--引导和退出iWebOffice-->
修改为:
<body bgcolor="#ffffff" onUnload="UnLoad()"> <!--引导和退出iWebOffice-->
2.5
修改程序中一些在iWebOffice2015不支持的事件,如
iWebOffice2003&iWebOffice2009中的OnMenuClick()事件需要更换成iWebOffice2015中OnCommand()事件:
iWebOffice2003中的代码如下
<script language="javascript" for=WebOffice event="OnMenuClick(vIndex,vCaption)">
if (vIndex==1){
WebOpenLocal(); //打开本地文件
}
if (vIndex==2){
WebSaveLocal(); //保存本地文件
}
if (vIndex==3){
SaveDocument(); //保存正文到服务器上(不退出)
}
if (vIndex==5){
WebOpenSignature(); //签名印章
}
if (vIndex==6){
WebShowSignature(); //验证签章
}
if (vIndex==8){
WebSaveVersion(); //保存版本
}
if (vIndex==9){
WebOpenVersion(); //打开版本
}
if (vIndex==11){
SaveDocument(); //保存正文到服务器上
webform.submit(); //然后退出
}
if (vIndex==13){
WebOpenPrint(); //打印文档
}
</script>
替换为:
<script language="javascript" for=WebOffice2015 event="OnCommand(ID, Caption, bCancel)">
if (ID==1){
WebOpenLocal(); //打开本地文件
}
if (ID==2){
WebSaveLocal(); //保存本地文件
}
if (ID==3){
SaveDocument(); //保存正文到服务器上(不退出)
}
if (ID==5){
WebOpenSignature(); //签名印章
}
if (ID==6){
WebShowSignature(); //验证签章
}
if (ID==8){
WebSaveVersion(); //保存版本
}
if (ID==9){
WebOpenVersion(); //打开版本
}
if (ID==11){
SaveDocument(); //保存正文到服务器上
webform.submit(); //然后退出
}
if (ID==13){
WebOpenPrint(); //打印文档
}
</script>
第三:
如果是原项目中没有任何版本的WebOffice的,直接集成最新的WebOffice2015即可,具体做法:
3.1
图片中红色框中的内容是需要导入进项目中的。具体做法图片中的文档中也有介绍。我这里自己写一点,大家可以参考一下。
将css包中导入、将js中的文件导入、将samples文件夹中OpenAndSave文件夹中的
导入。这个jsp页面主要是负责word的在线编辑功能;将web-inf 中的lib下的jar包导入,这里后台代码主要是链接的Oracle数据库,如果链接其他数据库需要导入新的jar包。
核心处理类导入,
辅助类导入。至此全部导入和基础工作就做完了。。。。接下来是具体项目的集成问题;上述问题需要注意的几点:
1.如果项目中之前集成过,必须要升级版本至2015,如果没有集成过,按照我上面写的,或者文件夹中的文档一步一步将jar包、js、css、处理类等放到具体的项目中
2.js的位置、css的位置等需要明确、到时候页面中需要引入的时候不要引入错误的、不正确的位置。
3.隐藏的up和down目录不用管、后期功能实现会自动创建
第四:页面实现:
4.1 打开文档实现
找一个需要将功能集成的页面,将“在线编辑”的功能集成。
首先引导到OpenAndSave_Word.jsp。之后在OpenAndSave_Word.jsp页面中,引入刚才导入的js、css等文件。
<%@ page contentType="text/html; charset=utf-8" %>
<%@ page import="java.io.*,java.text.*,java.util.*,java.sql.*,java.text.SimpleDateFormat,java.text.DateFormat,java.util.Date,javax.servlet.*,javax.servlet.http.*,DBstep.iDBManager2000.*" %>
<%
//自动获取OfficeServer和OCX文件完整URL路径
String mHttpUrlName=request.getRequestURI();
String mScriptName=request.getServletPath();
String mServerName="OfficeServer";
String mServerUrl="http://"+request.getServerName()+":"+request.getServerPort()+mHttpUrlName.substring(0,mHttpUrlName.lastIndexOf(mScriptName))+"/"+mServerName;//取得OfficeServer文件的完整URL
System.out.println(mServerUrl);
%>
<html>
<head>
<title>在线打开/保存Word文档
</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="../../js/WebOffice.js">
</script>
<script type="text/javascript">
var WebOfficeObj =
new WebOffice2015();
//创建WebOffice对象
</script>
<script language="javascript">
//有进度条打开文档
function Load()
{
try
{
WebOfficeObj.WebUrl =
"<%=mServerUrl%>";
WebOfficeObj.UserName =
"演示人";
WebOfficeObj.RecordID =
"123456789";
WebOfficeObj.FileName =
"sample.doc";
WebOfficeObj.FileType =
".doc";
//FileType:文档类型 .doc .xls
WebOfficeObj.DebugMode =
false;
//开启or关闭调试模式 true:开启 false:关闭
WebOfficeObj.ShowWindow =
true;
//true显示进度条//false隐藏进度条
WebOfficeObj.EditType =
"1";
//设置加载文档类型 0 锁定文档,1无痕迹模式,2带痕迹模式
WebOfficeObj.ShowMenu =
0;
WebOfficeObj.ShowToolBar =
0;
// WebOfficeObj.SetCaption(WebOfficeObj.UserName + "正在编辑文档");
SetGraySkin();
//设置控件皮肤
if(WebOfficeObj.WebOpen())
{
StatusMsg(WebOfficeObj.Status);
}
}
catch(e){
StatusMsg(e.description);
}
}
//无进度条打开文档
function LoadNoShowProgress()
{
try
{
WebOfficeObj.WebUrl =
"<%=mServerUrl%>";
WebOfficeObj.UserName =
"演示人";
WebOfficeObj.FileName =
"sample.doc";
WebOfficeObj.FileType =
".doc";
//FileType:文档类型 .doc .xls
WebOfficeObj.DebugMode =
false;
//开启or关闭调试模式 true:开启 false:关闭
WebOfficeObj.ShowWindow =
false;
//true显示进度条//false隐藏进度条
WebOfficeObj.EditType =
"1";
//设置加载文档类型 0 锁定文档,1无痕迹模式,2带痕迹模式
WebOfficeObj.ShowMenu =
0;
WebOfficeObj.ShowToolBar =
0;
// WebOfficeObj.SetCaption(WebOfficeObj.UserName + "正在编辑文档");
SetGraySkin();
//设置控件皮肤
if(WebOfficeObj.WebOpen())
{
StatusMsg(WebOfficeObj.Status);
}
}
catch(e){
StatusMsg(e.description);
}
}
//保存文档
function SaveDocument()
{
if (WebOfficeObj.WebSave()){
//交互OfficeServer的OPTION="SAVEFILE"
WebOfficeObj.WebClose();
window.close();
}
else{
alert(WebOfficeObj.Status);
StatusMsg(WebOfficeObj.Status);
}
}
//设置页面中的状态值
function StatusMsg(mValue) {
try {
document.getElementById(
'StatusBar').value = mValue;
}
catch (e) {
return
false;
}
}
//烟枪灰皮肤
function SetGraySkin(){
//参数顺序依次为:控件标题栏颜色、自定义菜单开始颜色、自定义工具栏按钮开始颜色、自定义工具栏按钮结束颜色、
//自定义工具栏按钮边框颜色、自定义工具栏开始颜色、控件标题栏文本颜色(默认值为:0x000000)
if (!WebOfficeObj.WebSetSkin(
0xdbdbdb,
0xeaeaea,
0xeaeaea,
0xdbdbdb,
0xdbdbdb,
0xdbdbdb,
0x000000))
alert(WebOfficeObj.Status);
}
function OnUnLoad(){
WebOfficeObj.WebClose();
}
//前后台交互,key在后台接收
function SendMessage()
{
var info =
window.prompt(
"请输入要传到服务器处理页面上的内容:",
"参数内容");
if (info==
null){
return
false}
WebOfficeObj.WebSetMsgByName(
"TESTINFO",info);
//USERNAME在后获取
if(WebOfficeObj.WebSendMessage()){
// 交互信息为INPORTTEXT
alert(WebOfficeObj.WebGetMsgByName(
"RETURNINFO"));
//USERNAME值为对应后台的key
}
else{
alert(
"客户端Web发送数据包命令没有合适的处理函数");
}
}
</script>
<script language="javascript" for="WebOffice" event="OnReady()">
WebOfficeObj.setObj(
document.getElementById(
'WebOffice'));
//给2015对象赋值
Load();
//避免页面加载完,控件还没有加载情况
</script>
<!--以下是多浏览器的事件方法 -->
<script>
function OnReady(){
WebOfficeObj.setObj(
document.getElementById(
'WebOffice'));
//给2015对象赋值
//Load();//避免页面加载完,控件还没有加载情况
window.onload =
function(){Load();}
//IE和谷歌可以直接调用Load方法,火狐要在页面加载完后去调用
}
</script>
</head>
<body onbeforeunload="OnUnLoad()" onUnload="OnUnLoad();">
<div style="width: 100%; height: 100%">
<div style="width: 100%;">
<input style="color:Red;" type=button value="无进度条打开文档" onclick="OnUnLoad();LoadNoShowProgress()">
<input style="color:Red;" type=button value="有进度条打开文档" onclick="OnUnLoad();Load()">
<input style="color:Red;" type=button value="保存文档到服务器" onclick="SaveDocument()">
<input style="color:Red;" type=button value="打开本地文档(有窗口)" onclick="WebOfficeObj.WebOpenLocal()">
<input style="color:Red;" type=button value="保存本地文档(有窗口)" onclick="WebOfficeObj.WebSaveLocal()">
<input style="color:Red;" type=button value="前后台交互信息" onclick="SendMessage()">
<input style="color:Red;" id="StatusBar" type="text" name="StatusBar" readonly style="WIDTH:40%">
|←状态信息
</div>
<div style="width: 100%; height: 98%;" >
<script src="../../js/iWebOffice2015.js">
</script>
</object>
</div>
</div>
</body>
<script language="javascript">
var i =
document.getElementById(
'WebOffice').height =
document.documentElement.clientHeight
-50 +
"px";
document.getElementById(
'WebOffice').style.height = i;
window.onresize =
function(){
var i =
document.getElementById(
'WebOffice').height =
document.documentElement.clientHeight
-50 +
"px";
document.getElementById(
'WebOffice').style.height = i;
};
</script>
</html>
在这个页面中,html部分不多解释,需要的功能你就用,不用的直接注释。不多解释。这里只讲在线打开文档和在线编辑的两个功能。实现童鞋想要实现别的功能的话,那你看到这里就关了吧。
html中有两个关于文档打开的功能,一个是无进度条打开文档
<input style="color:Red;" type=button value="无进度条打开文档" onclick="OnUnLoad();LoadNoShowProgress()">
一个是有进度条打开文档
<input style="color:Red;" type=button value="有进度条打开文档" onclick="OnUnLoad();Load()">
实际两个是一个方法,大同小异,只是在配置参数的时候多了一个窗口加载时的配置,WebOfficeObj.ShowWindow = true; 用一个就行。
自动保存(也就是在线编辑)这个方法是SaveDocument,实际也就是用到这两个。下面进入正题直接贴代码
官网:
官网给的demo,这里WebOfficeObj这个对象的基本属性配置以及赋值我就不多说了,说说我的做法:我这里是在load加载前,将需要打开的文档的名称(数据库中的唯一标识:时间戳+uuid)传递过来,也就是直接加载我所想要的文档,不过这一点,WebOffice也已经做到了,这个Load在页面初始化的时候就已经加载了。
我的代码:
其中后期用到的最关键的就是fileName这个字段,里面存放了文档的名称,其他的:uploadPersion、contype、conid等等看你后期在核心处理类中想要什么再传递什么。。。。。。。。。。。。
jsp页面中就这么点东西。。。配置完前期参数、属性值接下来就是js文件夹中的核心js处理了
WebOfficeObj对象的WebOpen方法进入
官网的demo给的已经很详细了,所有的属性值基本都有注释
看到这里,之前页面上赋值的对象,也存在这里,如果后期根据实际业务你需要更多的字段来存储信息,在这里直接定义就好。
官网提供的demo文件基本都不用改什么,这里强调几点,在这个方法中
this.WebOpen = function(mBoolean)
{
this.ConsoleOut(
"<WebOpen> 开始...");
this.Status =
"";
var httpclient =
this.obj.Http;
// 设置http对象
httpclient.Clear();
this.WebSetMsgByName(
"USERNAME",
this.UserName);
// 加载UserName
this.WebSetMsgByName(
"FILENAME",
this.FileName);
// 加载FileName
this.WebSetMsgByName(
"FILETYPE",
this.FileType);
// 加载FileType
this.WebSetMsgByName(
"RECORDID",
this.RecordID);
// 加载RecordID
this.WebSetMsgByName(
"EDITTYPE",
this.EditType);
// 加载RecordID
this.WebSetMsgByName(
"OPTION",
"LOADFILE");
// 发送请求LOADFILE
httpclient.AddForm(
"FormData",
this.GetMessageString());
// 这里是自定义json
// 传输格式。
this.WebClearMessage();
// 清除所有WebSetMsgByName参数
this.sendMode =
"OpenFile";
this.ConsoleOut(
"<WebOpen> 开始下载文档...");
this.NewShowMenu(
this.ShowMenu);
//控制菜单栏是否可以显示
this.NewShowToolBar(
this.ShowToolBar);
//控制Office工具栏和自定义工具栏
if (
this.LOADFILE(httpclient))
// Http下载服务器文件
{
this.NewCopyType(
this.CopyType);
//控制是否可以复制
this.NewUIControl(
this.UIControl);
//控制 2010保存跟另存为
this.ConsoleOut(
"<WebOpen> 成功...");
var httpclient =
this.obj.Http;
var ISO = httpclient.GetResponseHeader(
"ISO");
// 获取返回值
if(
this.FileType !=
".ppt" &&
this.FileType !=
".pptx"){
this.VBASetUserName(
this.UserName);
}
this.setEditType(
this.EditType);
//设置文档编辑权限 0 、只读不能复制 1、无痕迹打开 2、有痕迹打开
this.Status =
"打开文档成功";
// Status:状态信息
return
true;
}
else {
//this.Status = "打开文档失败"; // Status:状态信息 由This.LOADFILE返回
return
false;
}
}
this.WebSetMsgByName("USERNAME", this.UserName); // 加载UserName
this.WebSetMsgByName("FILENAME", this.FileName); // 加载FileName
this.WebSetMsgByName("FILETYPE", this.FileType); // 加载FileType
this.WebSetMsgByName("RECORDID", this.RecordID); // 加载RecordID
this.WebSetMsgByName("EDITTYPE", this.EditType); // 加载RecordID
this.WebSetMsgByName("OPTION", "LOADFILE"); // 发送请求LOADFILE
从jsp页面中之前定义属性获取值。
if (this.LOADFILE(httpclient)) // Http下载服务器文件
this.LOADFILE(httpclient))方法从服务器开始下载文件,代码中
this.LOADFILE = function(httpclient)
{
this.Status =
"";
httpclient.ShowProgressUI =
this.ShowWindow;
this.ConsoleOut(
"<LOADFILE> 开始打开链接...");
if (httpclient.Open(
this.HttpMethod.Post,
this.WebUrl,
false))
// true
// 异步方式
// false同步
{
this.ConsoleOut(
"<LOADFILE> 链接打开成功,开始进行数据包发送...");
// 这里采用异步方式打开文档
if (httpclient.Send()) {
this.ConsoleOut(
"<LOADFILE> 数据包发送成功...状态值:"+httpclient.GetResponseHeader(
"MsgError"));
if (httpclient.GetResponseHeader(
"MsgError") ==
"404") {
this.ConsoleOut(
"<LOADFILE> 后台未找到对应文档,开始创建一个空白文档...");
this.CreateFile();
this.ConsoleOut(
"<LOADFILE> 空白文档创建成功...");
this.getOfficeVersion();
// 打开文档后,判断当前office版本
httpclient.Clear();
return
true;
}
this.ConsoleOut(
"<LOADFILE> 开始将后台文档保存到本地...");
/*
* , Math.round(Math.random() * 100000)
*/
if (
this.hiddenSaveLocal(httpclient,
this,
false,
false)) {
var mSaveResult =
this
.WebOpenLocalFile(
this.DownloadedFileTempPathName);
if (mSaveResult ==
0) {
// 打开本地磁盘文件
this.ConsoleOut(
"<LOADFILE> 文档打开成功...");
this.getOfficeVersion();
// 打开文档后,判断当前office版本
return
true;
}
else
if(mSaveResult ==
1){
var windows = window.confirm(
"可能当前授权码错误,请确认iWebOffice2015.js的授权是否正确(或乱码)"
+
"\r\r单击“确定”关闭。单击“取消”继续。");
this.Status =
"可能当前授权码错误,请确认iWebOffice2015.js的授权是否正确(或乱码)";
if (windows ==
1) {
window.close();
return
false;
}
}
else
if(mSaveResult ==
2){
var windows = window.confirm(
"没有找到文档,请确认WebOpenLocalFile打开文档的路径是否正确"
+
"\r\r单击“确定”关闭。单击“取消”继续。");
this.Status =
"有找到文档,请确认WebOpenLocalFile打开文档的路径是否正确";
if (windows ==
1) {
window.close();
return
false;
}
}
else
if(mSaveResult ==
3){
var windows = window.confirm(
"没有权限导致文档打开失败,请用管理员身份运行浏览器后重试"
+
"\r\r单击“确定”关闭。单击“取消”继续。");
this.Status =
"没有权限导致文档打开失败,请用管理员身份运行浏览器后重试";
if (windows ==
1) {
window.close();
return
false;
}
}
else
if(mSaveResult ==
4){
var windows = window.confirm(
"文件可能损坏,请确定服务器文档是否已经损坏"
+
"\r\r单击“确定”关闭。单击“取消”继续。");
this.Status =
"文件可能损坏,请确定服务器文档是否已经损坏";
if (windows ==
1) {
window.close();
return
false;
}
}
else
if(mSaveResult ==
5){
var windows = window.confirm(
"未安装Office或者注册表有损坏"
+
"\r\r单击“确定”关闭。单击“取消”继续。");
this.Status =
"未安装Office或者注册表有损坏";
if (windows ==
1) {
window.close();
return
false;
}
}
else
if(mSaveResult ==
6){
var windows = window.confirm(
"文件被占用,请结束Office进程后重试"
+
"\r\r单击“确定”关闭。单击“取消”继续。");
this.Status =
"文件被占用,请结束Office进程后重试";
if (windows ==
1) {
window.close();
return
false;
}
}
else {
this.ConsoleOut(
"<LOADFILE> 打开文档时未知错误!错误码为: "
+ mSaveResult);
var windows = window.confirm(
"打开文档时未知错误!错误码为: "
+ mSaveResult
+
"\r\r单击“确定”关闭。单击“取消”继续。");
this.Status =
"打开文档时未知错误!错误码为: "
+ mSaveResult;
if (windows ==
1) {
window.close();
return
false;
}
}
}
else {
// 失败后,this.Status的值由hiddenSaveLocal返回
this.Status =
"保存文档到本地 失败";
return
false;
}
}
else {
this.Status =
"数据包发送失败!请检查链接<" +
this.WebUrl +
">是否正确或网络是否畅通。";
return
false;
}
}
else {
this.Status =
"打开链接<" +
this.WebUrl +
">失败!请检查网络是否畅通。";
return
false;
}
}
加载文档的原理:采用http请求的方式,采用异步来实现文档加载:if (httpclient.Open(this.HttpMethod.Post, this.WebUrl, false)) // true。第一个参数固定不变,是模拟http的post请求、第二个参数:this.WebUrl内放置的即使我们的后台核心处理类的地址、第三个参数是异步同步的设置;
加载文档的核心处理类:这里后台文件OfficeServer我们需要按实际业务需求更改一下,这里我直接贴我的代码,由于我们只先说文档打开,所以就只贴一部分代码了,经过http请求响应的核心处理类OfficeServer;
加载文档的核心处理方法:核心方法是protected void service(){
}
方法体:
logger.info(
"进入service方法");
this.mCommand =
"";
this.mFileBody =
null;
this.mFilePath = request.getSession().getServletContext().getRealPath(
"/");
try {
if (request.getMethod().equalsIgnoreCase(
"POST")) {
this.MsgObj.setSendType(
"JSON");
//文件上传
this.MsgObj.Load(request);
this.mOption =
this.MsgObj.GetMsgByName(
"OPTION");
this.mUserName =
this.MsgObj.GetMsgByName(
"USERNAME");
//20190403
if (
this.mOption.equalsIgnoreCase(
"LOADFILE")) {
//如果是下载模式
this.mRecordID =
this.MsgObj.GetMsgByName(
"RECORDID");
this.mFileName =
this.MsgObj.GetMsgByName(
"FILENAME");
this.MsgObj.MsgTextClear();
this.mFilePath =
this.mFilePath.replace(
'\\',
'/');
// web跟目录
this.mFilePath =
this.mFilePath +
"upload_files";
String finalAdd =mFilePath+
"/"+mFileName;
if(MsgObj.MsgFileLoad(finalAdd)){
System.
out.println(
"文档加载成功");
}
else{
System.
out.println(
"文档加载失败");
}
代码中 this.mFilePath即使你tomcat下面的附件文件夹地址
接下来是 MsgObj.MsgFileLoad方法
public boolean MsgFileLoad(String fileName) throws IOException
{
File f =
new File(fileName);
if (!f.exists()) {
throw
new FileNotFoundException(fileName);
}
ByteArrayOutputStream bos =
new ByteArrayOutputStream((
int)f.length());
BufferedInputStream in =
null;
try {
in =
new BufferedInputStream(
new FileInputStream(f));
int buf_size =
1024;
byte[] buffer =
new
byte[buf_size];
int len =
0;
while (-
1 != (len = in.read(buffer,
0, buf_size))) {
bos.write(buffer,
0, len);
}
this.mFileBody = bos.toByteArray();
return
true;
}
catch (IOException e) {
e.printStackTrace();
throw e;
}
finally {
try {
in.close();
}
catch (IOException e) {
e.printStackTrace();
}
bos.close();
}
}
1
我们不需要修改什么地方。直接引用官网给的demo就行。
总结:
一:js文件
1.1 页面中需要引入的属性设置
二:核心处理类
2.后台文件需要修改的只是将 this.mFilePath 定义为自己的tomcat附件的文件夹地址
成果展示
左上角根据实际业务需求,只开放了打开文档(打开文档之前提过,页面初始化,带着提前准备的参数,已经打开)、保存到服务器两个功能。
打开文档之后,可以在线编辑文档,word自己带的功能,在这里全部都适用,这点不用担心。
修改文档之后就开始保存了,接下来就是保存文档的正题。
4.2 在线编辑以及服务器保存实现
老样子,直接贴代码
OpenAndSave_Word.jsp中
//保存文档 function SaveDocument() { if (WebOfficeObj.WebSave()) { //交互OfficeServer的OPTION="SAVEFILE" WebOfficeObj .WebClose(); window .close(); } else { alert(WebOfficeObj.Status); StatusMsg(WebOfficeObj.Status); } }
WebOffice.js中
处理方法:
方法体:
this.ConsoleOut( "<WebSave> 保存文件..."); this.ConsoleOut( "<WebSave> 开始..."); this.Status = ""; var httpclient = this.obj.Http; // 设置http对象 httpclient.Clear(); //一如既往,这里是属性赋值 this.WebSetMsgByName( "USERNAME", this.UserName); this.WebSetMsgByName( "RECORDID", this.RecordID); this.WebSetMsgByName( "TEMPLATE", this.Template); this.WebSetMsgByName( "SUBJECT", this.Subject); this.WebSetMsgByName( "AUTHOR", this.Author); this.WebSetMsgByName( "HTMLPATH", this.HTMLPath); this.WebSetMsgByName( "FILETYPE", this.FileType); this.WebSetMsgByName( "OPTION", "SAVEFILE"); this.WebSetMsgByName( "FILENAME", this.FileName); // 加载FileName //判断是否保存空文档的方法 if( this.WebSetAllowEmpty()){ //文档保存到本地 var mSaveResult = this.WebSaveLocalFile( this.getFilePath() + this.FileName); if (!(mSaveResult == 0)) { this.ConsoleOut( "<WebSave> 保存本地文档失败!错误代码为:" + mSaveResult); this.Status = "保存本地文档失败!错误代码为:" + mSaveResult; return false; } } else{ alert( "文档没有内容,是否确定保存"); } this.ConsoleOut( "<WebSave> 将文档保存到本地成功..."); this.sendMode = "SaveFile"; this.ConsoleOut( "<WebSave> 开始将文档保存到服务器..."); // 判断本地文件是否大于指定的文件大小,如果大于不保存 if ( this.WebSetMaxFileSize( this.FilePath + this.FileName)) { //这里需要将这个值传递到后台 var add = this.FilePath + this.FileName; //这里需要将本地隐藏目录传递到后台。如果单一传递路径,json编译会出错,需要修改一下 //var add = add.replace("\\","\\\\"); var arrayStr = add.split( "\\"); this.WebSetMsgByName( "FILEPATH",arrayStr); //开始保存到服务器了 if ( this.SAVEFILE(httpclient, this.FilePath + this.FileName)) { this.ConsoleOut( "<WebSave> 成功将文档保存到服务器..."); var ISO = httpclient.GetResponseHeader( "ISO"); // 获取返回值 this.Status = "成功将文档保存到服务器"; return true; } else { //STATUS 由this.SAVEFILE返回 return false; } } else { this.Status = "保存失败:MaxFileSize只能允许保存:<" + this.MaxFileSize / 1024 + ">" + "M"; return false; }
这里得插几句我的思路和理解了。
所谓的在线编辑保存就是从服务器先获得你需要修改的文档也就是文档模板,之后将模板加载出来,这个时候WebOffice会将文档存放在一个叫做down的目录中(win+r 输入 %appdata% 看到一个)
之后我们开始文档编辑,编辑完,WebOffice会将这个形成的临时文件存放到隐藏目录叫做up的文件夹中,我们点击保存的时候,如果实际需求是不能覆盖原先模板,我们将存放在up中的文件实际完整地址获取到,将文件上传到我们的tomcat附件目录中,后期我们在数据库中通过版本控制,实现每次加载的模板总是最新的模板(最后修改人上传的文档模板)。
说了几句废话,开始继续贴代码
OfficeServer.java中
//20190403 文档在线编辑保存 else if ( this.mOption.equalsIgnoreCase( "SAVEFILE")) { this.mRecordID = this.MsgObj.GetMsgByName( "RECORDID"); this.mFileName = this.MsgObj.GetMsgByName( "FILENAME"); this.mFileType = this.MsgObj.GetMsgByName( "FILETYPE"); String userName = this.MsgObj.GetMsgByName( "USERNAME"); //这里这个路径 必须特殊处理掉 String mFilePath = this.MsgObj.GetMsgByName( "FILEPATH"); this.mFileBody = this.MsgObj.MsgFileBody(); this.mFileSize = this.MsgObj.MsgFileSize(); this.mFileDate = this.DbaObj.GetDateTime(); this.MsgObj.MsgTextClear(); //获取tomcat下面附件的地址 this.mFilePath = this.mFilePath.replace( '\\', '/'); // web跟目录 this.mFilePath = this.mFilePath + "upload_files"+ ""; String newPath = this.mFilePath+ "/"+mFileName; //得到旧的文件地址(文件的隐藏目录) 。 String oldPath =mFilePath.replace( ',', '/'); //自己定义的方法,主要是存数据库中 if (SaveFile( this.mRecordID, this.mFileName, this.mFileType, this.mFileBody, this.mFileSize, this.mFileDate,userName, newPath,oldPath)) { System. out.println( "文档保存成功"); } else{ System. out.println( "文档保存失败"); } }
这个方法主要是实现:获取自己想要存入数据库中的各个属性值、获得两个文件存储的完整目录,为后期上传做准备。
private boolean SaveFile( String mRecordID, String mFileName, String mFileType,byte [] mFileBody, int mFileSize, String mFileDate, String userName, String newPath, String oldPath ) { boolean mResult = false; try { Connection myconn = ConnectionManager.getDefaultConnection(); try { myconn.setAutoCommit( false); Statement stmt = myconn.createStatement(); ResultSet rs = null; //参数赋值 this.mFileType = mFileType; this.mUserName = userName; this.mFileName = mFileName; this.mFileSize = this.MsgObj.MsgFileSize(); String mxId = Asstool.getMaxHirisunId(); String uploadDate = Asstool.getSystemDatetimetostring(); try { //判断文档之前是否上传过 String Sql = "select t.conid from ulob.slavefiles t " + " where t.pk_id='"+mRecordID+ "' " + " order by t.uploaddate desc"; List list = SingleTableOperation.getSimpleRecords(Sql); if( list.size()> 0){ //此文档之前上传过 //取出主表id 去查询明细 String conId = (( List)( list.get( 0))).get( 0).toString(); //用之前存在子表中的字段更新即将插入的数据 String sqlSelectMx = "select t1.* from ulob.slavefiles_version t1 " + " where t1.recordid='"+conId+ "' " + " order by t1.history desc"; List listMx = SingleTableOperation.getSimpleRecords(sqlSelectMx); if(listMx.size()> 0){ List listOne =( List) listMx.get( 0); //ulob.slavefiles 主键 。作为子表的引用 String recordId = listOne.get( 0).toString(); //人名 String userName1 = this.mUserName; //版本号 String history = listOne.get( 5).toString(); //表id String Mxid = mxId; //大小 int fileSize = this.mFileSize; String fileName = ( new Date()).getTime()+recordId+this.mFileType; //路径不变。但是得截取只要纯路径 不含名字 String filePath = listOne.get( 3).toString(); filePath = filePath.substring( 0,filePath.lastIndexOf( "/")); filePath = filePath+ "/"+fileName; // String inedit = listOne.get( 9).toString(); try { //在线编辑 分为两步:第一步插入数据库 。第二步复制隐藏目录下的文件到 系统的附件文件夹 String insertSql = " insert into ulob.slavefiles_version " + " (recordid,filedate,filebody,filepath,username,history,id,filesize,filename,isedit,edituser,editdata ) " + " values('"+recordId+ "',to_date('"+uploadDate+ "','yyyy-mm-dd hh24:mi:ss'),empty_blob(),'"+filePath+ "','"+userName1+ "','" + String.valueOf(( Integer.parseInt(history)+ 1))+ "','"+Mxid+ "','"+fileSize+ "','"+fileName+ "','"+inedit+ "','"+userName+ "',to_date('"+uploadDate+ "','yyyy-mm-dd hh24:mi:ss')) "; //更新 TableOperation.ExecuteUpdateSQL(insertSql); rs = stmt .executeQuery( "select filebody from ulob.slavefiles_version t where='" + Mxid + "' for update"); //实现在线编辑的第一部分: if (rs.next()) { Blob blob = rs.getBlob( 1); OutputStream out = ((oracle.sql.BLOB) blob) .getBinaryOutputStream(); byte[] b = new byte[((oracle.sql.BLOB) blob) .getBufferSize()]; File file = new File(oldPath); InputStream fis = new FileInputStream(file); int len = 0; while ((len = fis.read(b)) != -1) out.write(b, 0, len); out.close(); myconn.commit(); mResult= true; } } catch ( Exception e) { // TODO: handle exception e.printStackTrace(); } finally { myconn.close(); this.MsgObj.MsgFileSave(filePath); //zhazha } } } } catch ( Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } catch (SQLException e1) { e1.printStackTrace(); } catch ( Exception e1) { e1.printStackTrace(); } } catch ( Exception e1) { e1.printStackTrace(); } return (mResult); }
总结:
保存文档:第一部分,将数据存入数据库;第二部分,获取两个路径,将文件转移;
this.MsgObj.MsgFileSave(filePath) 提供了文件的上传,filePath是目标文件的全路径。
如果上面的工作全部完成了,那么恭喜你,你的项目走到这一步将出现一个巨大的bug。。。。。。。。。。。。。。。
WebOffice官网下载的demo在文档保存的时候,你会发现,保存到目标目录中的文件全是空文件,观察后台发现会出现一个错误
造成的原因:
public byte[] MsgFileBody() throws IOException { this.mFileBody = null; /* ByteArrayOutputStream output = new ByteArrayOutputStream(); byte[] buffer = new byte[ 4096]; int n = 0; while ( -1 != (n = this.fileContentStream. read(buffer))) { output. write(buffer, 0, n); } this.mFileBody = output.toByteArray(); this.FFileSize = this.mFileBody.length; this.fileContentStream. close();*/ return this.mFileBody; }
在将文本封装MsgFileBody中的时候,this.fileContentStream.close();将流关闭掉了,后期引入demo的时候,虽然数据库中是存入了文本,但是保存目标文件的时候,目标文件因为刘关闭,获取不到文本,所以出现保存空文本,正确的做法是将这段内容注释掉。
前提:采用的思路是我这种通过版本控制实现获取最新上传文件,以及数据库中之存入版本号,文本内容存不存都可以的方法。
以上就是全部内容了。。。。。。。。。。。。。。。。。。。。。。不喜勿喷。。欢迎一起讨论。。。。。。。。。。。