使用iWebOffice实现电子签章
摘要:隨著信息化的發展電子簽章已經越來越多的被用到很多OA系統中,今天就來看一下如何使用iWebOffice來實現電子簽章功能。
內容:
1.iWebOffice2003的基本原理
2.使用iWebOffice2003實現電子簽章
一、iWebOffice2003的基本原理
在開始今天的主題之前先簡單的說一下iWebOffice的原理。iWebOffice控件由兩部分組成:一個是用于集成在頁面上的iWebOffice2003.ocx文件,另一個是運行在后臺服務器上的iMsgServer2000.dll文件。前者就是大家所熟知的ActiveX插件,當然要使用它在客戶端必須安裝此插件,后者是用于配合前者的請求進行通信,事實上控件工作的原來正是前后臺通信和處理的過程。iWebOffice2003.ocx集成在頁面上,通過js腳本調用,用戶文檔的編輯以及傳遞消息到服務器;iMsgServer2000.dll在服務器端運行,用于解析iWebOffice2003.ocx控件發過來的信息包,以及將服務器上處理的結果反饋給客戶端iWebOffice2003.ocx。
首先來看前端的代碼,可以說同其他ActiveX幾乎完全一樣。classid是固定的,是控件的注冊id,這也是所有com組件必須擁有的;codebase由兩部分組成#version之前的是控件的下載地址,后面是控件版本號,這兩者當然務必要寫正確,否則會造成控件不能正常下載、顯示和使用。
前端頁面代碼:
<OBJECT id="CWebOffice" width="100%" height="100%" classid="clsid:23739A7E-5741-4D1C-88D5-D50B18F7C347" codebase=" iWebOffice2003.ocx#version=6,0,0,4 " ></OBJECT>如果classid和version沒有設置錯的話運行會顯示控件(前提是客戶端安裝了iWebOffice插件),當然此時還不能打開文檔,因為前端還沒有js調用。為了方便調用,這里將js操作部分加以封裝(注意封裝部分用到了Ext面向對象):
?
/*Author:KenshinCuiDate:2011.11.16Description:weboffice operate class. */ Ext.useShims=true; Ext.namespace("Cmj.Web.ExtExtend"); Cmj.Web.ExtExtend.WebOffice=Ext.extend(Ext.util.Observable,{constructor:function(config){ // this.addEvents("beforeopen"); // this.addEvents("open"); // this.addEvents("beforeprint"); // this.addEvents("print"); // this.addEvents("beforeopen"); // this.addEvents("open"); // this.addEvents("beforeopen"); // this.addEvents("open");this.listeners=config.listeners;Cmj.Web.ExtExtend.WebOffice.superclass.constructor.call(this,config);this.objectID=config.objectID;//客戶端對象idthis.webUrl=config.webUrl;//weboffice 的服務器端操作urlthis.fileName=config.fileName;//文件名稱(不包含完整路徑并且后綴可有可無,如果沒有后綴的話則必須配置fileType屬性)if(config.fileType!=void 0){this.fileType=config.fileType;}else{this.fileType="";}this.webOffice=Ext.getDom(this.objectID);},getObject:function(){return this.webOffice;},load:function(){WebOffice=this.webOffice;try{WebOffice.WebUrl=this.webUrl;WebOffice.RecordID="cid";WebOffice.Template="";WebOffice.FileName=this.fileName;WebOffice.FileType=this.fileType;WebOffice.EditType="1";WebOffice.UserName="SYSTEM";WebOffice.WebOpen(); //打開該文檔 window.status=WebOffice.Status;}catch(e){Ext.Msg.alert("系統提示","打開文檔過程中發生錯誤,錯誤信息:"+e.message);}},showMenu:function(bool){try{this.webOffice.ShowMenu=bool?"1":"0";}catch(e){Ext.Msg.alert("系統提示","設置菜單顯示狀態時發生錯誤,錯誤信息:"+e.message);}},addMenus:function(menuArray){try{var menu=Ext.getDom('menuEventScript');for(var i=1;i<=menuArray.length;++i){if(menuArray[i-1]=="save"){this.webOffice.AppendMenu(i,"保存");menu.text+="if(Index=="+i+"){Ext.getDom('CWebOffice').WebSave();}"; }else if(menuArray[i-1]=="saveAs"){this.webOffice.AppendMenu(i,"另存為");menu.text+="if(Index=="+i+"){Ext.getDom('CWebOffice').WebSaveLocal();}"; }else if(menuArray[i-1]=="print"){this.webOffice.AppendMenu(i,"打印");menu.text+="if(Index=="+i+"){Ext.getDom('CWebOffice').WebOpenPrint();}"; }else if(menuArray[i-1]=="signature"){this.webOffice.AppendMenu(i,"電子簽章");menu.text+="if(Index=="+i+"){Ext.getDom('CWebOffice').WebOpenSignature();}"; }}}catch(e){Ext.Msg.alert("系統提示","創建菜單過程中發生錯誤,錯誤信息:"+e.message);}},save:function(){//保存到服務器try{this.webOffice.WebSave();}catch(e){Ext.Msg.alert("系統提示","文檔保存時發生錯誤,錯誤信息:"+e.message);}},saveAs:function(){//另存到客戶端try{this.webOffice.WebSaveLocal();}catch(e){Ext.Msg.alert("系統提示","文檔另存時發生錯誤,錯誤信息:"+e.message);}},print:function(){try{this.webOffice.WebOpenPrint();}catch(e){Ext.Msg.alert("系統提示","文檔打印時發生錯誤,錯誤信息:"+e.message);}},signature:function(type){//打開電子簽章操作窗口try{if(arguments.length>0){this.webOffice.WebOpenSignature(type);}else{this.webOffice.WebOpenSignature();}}catch(e){Ext.Msg.alert("系統提示","打開電子簽章窗口時發生錯誤,錯誤信息:"+e.message);}}});這里繼承了Ext的Observable類方便對于事件管理(這里由于只是簡單的演示因此事件部分注釋掉了,需要的話可以加上)。首先在構造函數部分取得webOffice對象,getObject()方法用戶向外部公開此對象。文檔加載在load()方法中,從代碼可以看出打開一個文檔只需要設置WebUrl(后臺http接口)、FileName(文件名)和Filetype(文件類型)屬性,然后調用WebOpen()方法。值得一提的是addMenus()方法,這個方法用于創建菜單,但是注意菜單的創建是通過動態構建js動態創建的。正常使用菜單的方法是頁面添加如下腳本(這里用到了控件的"OnMenuClick"事件):
<script language="javascript" for=WebOffice event="OnMenuClick(vIndex,vCaption)"> alert('編號:'+vIndex+'\n\r'+'條目:'+vCaption+'\n\r'+'請根據這些信息編寫菜單具體功能');if (vIndex==10){ …}; if (vIndex==11){ …};… </script>然后通過調用WebOffice的AppendMenu()方法進行添加:
webform.WebOffice.AppendMenu("10","測試菜單一"); webform.WebOffice.AppendMenu("11","測試菜單二"); webform.WebOffice.AppendMenu("12","-"); webform.WebOffice.AppendMenu("13","測試菜單四"); webform.WebOffice.AppendMenu("14","測試菜單五"); //其中:“-”表示分割線,增加的順序是在現有按鈕的最前面。 webform.WebOffice.AppendMenu("主菜單",""); //添加主菜單: webform.WebOffice.AppendMenu("15","測試菜單七(&C)"); webform.WebOffice.AppendMenu("16","測試菜單八(&D)");在WebOffice類中這部分代碼及判斷邏輯由js動態構建,實現菜單的可定制化。
其他方法都比較簡單,這里不再贅余。有了這個WebOffice.js類之后只需要簡單調用即可:
Ext.onReady(function(){var menus=["save","saveAs","print","signature"];var webOffice=new Cmj.Web.ExtExtend.WebOffice({objectID:'CWebOffice',webUrl:'HTTP://<%=host %>/WebOffice/OfficeServer.aspx',fileName:'<%=fileName %>',fileType:'<%= fileType%>'});webOffice.addMenus(menus);webOffice.load();});前端代碼完成了,但是服務器端如何配合前端處理呢,下面的服務器端處理類OfficeServer:
using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.IO; using System.Text; using DBstep;namespace DigitalSignature.WebOffice {public partial class OfficeServer : System.Web.UI.Page{private iMsgServer2000 msgServer = null;//服務器端weboffice控件private const string _FilePath = @"Document\";private const string _signatureFilePath = @"Signature\";private string mMarkList = "KenshinCui";private byte[] mFileBody = null;//簽章信息private string mOption;private string mRecordID;private string mTemplate;private string mFileName;private string mFileType;private string mHtmlName;private string mDirectory;private string mLabelName;private string mImageName;private string mCommand;protected void Page_Load(object sender, EventArgs e){string mFilePath;string TemplateFilePath;msgServer = new iMsgServer2000();string currentPath = ".";msgServer.MsgVariant(Request.BinaryRead(Request.ContentLength));mFilePath = ConfigurationManager.AppSettings["TempFile"]; //取得文檔的存放路徑TemplateFilePath = ConfigurationManager.AppSettings["Template"]; //取得存放模版文件的路徑if (mFilePath + "" == ""){mFilePath = Server.MapPath("/") +_FilePath;}currentPath = mFilePath;string n = msgServer.GetMsgByName("DBSTEP");if (n.Equals("DBSTEP")){mOption = msgServer.GetMsgByName("OPTION");if (mOption.Equals("LOADFILE")) //請求調用文檔{mRecordID = msgServer.GetMsgByName("RECORDID"); //取得文檔編號mFileName = msgServer.GetMsgByName("FILENAME"); //取得文檔名稱mFileType = msgServer.GetMsgByName("FILETYPE"); //取得文檔類型mFilePath = mFilePath + mFileName; //取得文檔完整路徑和名稱if (!Path.HasExtension(mFilePath)){mFilePath += mFileType;}msgServer.MsgTextClear();if (msgServer.MsgFileLoad(mFilePath)) //調入文檔{msgServer.SetMsgByName("STATUS", "打開成功!"); //設置狀態信息msgServer.MsgError(""); //清除錯誤信息}else{msgServer.MsgError("打開失敗!"); //設置錯誤信息}}else if (mOption.Equals("SAVEFILE")) //請求保存文檔{mRecordID = msgServer.GetMsgByName("RECORDID"); //取得文檔編號mFileName = msgServer.GetMsgByName("FILENAME"); //取得文檔名稱mFileType = msgServer.GetMsgByName("FILETYPE"); //取得文檔類型mFilePath = mFilePath + mFileName; //取得文檔完整路徑和名稱if (!Path.HasExtension(mFilePath)){mFilePath += mFileType;}msgServer.MsgTextClear();if (msgServer.MsgFileSave(mFilePath)) //保存文檔內容{msgServer.SetMsgByName("STATUS", "保存成功!"); //設置狀態信息msgServer.MsgError(""); //清除錯誤信息}else{msgServer.MsgError("保存失敗!" + mFileName); //設置錯誤信息}msgServer.MsgFileClear();}else if (mOption.Equals("LOADTEMPLATE")) //請求調用模板文檔{mTemplate = msgServer.GetMsgByName("TEMPLATE"); //取得文檔編號mFileType = msgServer.GetMsgByName("FILETYPE"); //取得文檔類型mFilePath = currentPath;mCommand = msgServer.GetMsgByName("COMMAND");if (mCommand.Equals("INSERTFILE")){msgServer.MsgTextClear();if (msgServer.MsgFileLoad(mFilePath + mTemplate)) //調入模板文檔{msgServer.SetMsgByName("STATUS", "打開模板成功!"); //設置狀態信息msgServer.MsgError(""); //清除錯誤信息}else{msgServer.MsgError("打開模板失敗!"); //設置錯誤信息}}else{mFilePath = TemplateFilePath + mTemplate + mFileType; //取得文檔完整路徑和名稱File.SetAttributes(mFilePath, FileAttributes.Normal);msgServer.MsgTextClear();if (msgServer.MsgFileLoad(mFilePath)) //調入模板文檔{msgServer.SetMsgByName("STATUS", "打開模板成功!"); //設置狀態信息msgServer.MsgError(""); //清除錯誤信息}else{msgServer.MsgError("打開模板失敗!"); //設置錯誤信息}File.SetAttributes(mFilePath, FileAttributes.ReadOnly | FileAttributes.Archive | FileAttributes.Compressed);}}else if (mOption.Equals("SAVETEMPLATE")) //請求保存模板文檔{mTemplate = msgServer.GetMsgByName("TEMPLATE"); //取得文檔編號mFileType = msgServer.GetMsgByName("FILETYPE"); //取得文檔類型mFilePath = TemplateFilePath + mTemplate + mFileType; //取得文檔完整路徑和名稱File.SetAttributes(mFilePath, FileAttributes.Normal);msgServer.MsgTextClear();if (msgServer.MsgFileSave(mFilePath)) //調入模板文檔{msgServer.SetMsgByName("STATUS", "保存模板成功!"); //設置狀態信息msgServer.MsgError(""); //清除錯誤信息}else{msgServer.MsgError("保存模板失敗!"); //設置錯誤信息}File.SetAttributes(mFilePath, FileAttributes.ReadOnly | FileAttributes.Archive | FileAttributes.Compressed);}else if (mOption.Equals("UPDATEFILE")) //請求保存文檔{mRecordID = msgServer.GetMsgByName("RECORDID"); //取得文檔編號mFileName = msgServer.GetMsgByName("FILENAME"); //取得文檔名稱mFileType = msgServer.GetMsgByName("FILETYPE"); //取得文檔類型mFilePath = mFilePath + mFileName; //取得文檔完整路徑和名稱msgServer.MsgTextClear();if (msgServer.MsgFileSave(mFilePath)) //保存文檔內容{msgServer.SetMsgByName("STATUS", "保存成功!"); //設置狀態信息msgServer.MsgError(""); //清除錯誤信息}else{msgServer.MsgError("保存失敗!"); //設置錯誤信息}msgServer.MsgFileClear();}else if (mOption.Equals("INSERTFILE")) //請求調用正文文檔{mRecordID = msgServer.GetMsgByName("RECORDID"); //取得文檔編號mFileName = msgServer.GetMsgByName("FILENAME"); //取得文檔名稱mFileType = msgServer.GetMsgByName("FILETYPE"); //取得文檔類型mFilePath = mFilePath + mFileName; //取得文檔完整路徑和名稱msgServer.MsgTextClear();if (msgServer.MsgFileLoad(mFilePath)) //調入文檔{msgServer.SetMsgByName("STATUS", "插入文件成功!"); //設置狀態信息msgServer.MsgError(""); //清除錯誤信息}else{msgServer.MsgError("插入文件失敗!"); //設置錯誤信息}}else if (mOption.Equals("INSERTIMAGE")) //請求調用正文文檔{mFilePath = currentPath;mRecordID = msgServer.GetMsgByName("RECORDID"); //取得文檔編號mLabelName = msgServer.GetMsgByName("LABLENAME"); //標簽名mImageName = msgServer.GetMsgByName("IMAGENAME"); //圖片名mFilePath = mFilePath + mImageName; //圖片在服務器的完整路徑mFileType = mImageName.Substring(mImageName.Length - 4, 4).ToLower(); //取得文件的類型msgServer.MsgTextClear();if (msgServer.MsgFileLoad(mFilePath)) //調入圖片{msgServer.SetMsgByName("IMAGETYPE", mFileType); //指定圖片的類型 msgServer.SetMsgByName("POSITION", mLabelName); //設置插入的位置[書簽對象名] msgServer.SetMsgByName("STATUS", "插入圖片成功!"); //設置狀態信息msgServer.MsgError(""); //清除錯誤信息}else{msgServer.MsgError("插入圖片失敗!"); //設置錯誤信息}}else if (mOption.Equals("SAVEASHTML")){mFilePath = currentPath;mHtmlName = msgServer.GetMsgByName("HTMLNAME"); //取得標簽文檔內容mDirectory = msgServer.GetMsgByName("DIRECTORY"); //取得標簽文檔內容msgServer.MsgTextClear();if (mDirectory.Equals("")){mFilePath = mFilePath + "\\HTML";}else{mFilePath = mFilePath + "\\HTML\\" + mDirectory;}msgServer.MakeDirectory(mFilePath);if (msgServer.MsgFileSave(mFilePath + "\\" + mHtmlName)){string txt = msgServer.MsgTextBody();byte[] biteBody = GetFileBody(mFilePath + "\\" + mHtmlName);Encoding encode = Encoding.GetEncoding("gb2312");string html = encode.GetString(biteBody);msgServer.MsgError(""); //清除錯誤信息msgServer.SetMsgByName("STATUS", "保存成功"); //設置狀態信息}else{msgServer.MsgError("保存失敗" + mFilePath + "\\" + mHtmlName); //設置錯誤信息}msgServer.MsgFileClear();}else if (mOption.Equals("SAVEIMAGE")){mFilePath = currentPath;mHtmlName = msgServer.GetMsgByName("HTMLNAME"); //取得標簽文檔內容mDirectory = msgServer.GetMsgByName("DIRECTORY"); //取得標簽文檔內容msgServer.MsgTextClear();if (mDirectory.Equals("")){mFilePath = mFilePath + "\\HTMLIMAGE";}else{mFilePath = mFilePath + "\\HTMLIMAGE\\" + mDirectory;}msgServer.MakeDirectory(mFilePath);if (msgServer.MsgFileSave(mFilePath + "\\" + mHtmlName)){msgServer.MsgError(""); //清除錯誤信息msgServer.SetMsgByName("STATUS", "保存成功"); //設置狀態信息}else{msgServer.MsgError("保存失敗"); //設置錯誤信息}msgServer.MsgFileClear();}else if (mOption.Equals("LOADMARKLIST"))//獲取電子印章列表{if (LoadMarkList()){ //獲得列表信息mMarkListmsgServer.SetMsgByName("MARKLIST", mMarkList); //顯示簽章列表(多個之間用換行符\r分割)msgServer.MsgError(""); //清除錯誤信息}else{msgServer.MsgError("創建印章列表失敗!"); //設置錯誤信息}}else if (mOption.Equals("LOADMARKIMAGE"))//打開印章文件{string mMarkName = msgServer.GetMsgByName("IMAGENAME"); //取得簽名名稱string mUserName = msgServer.GetMsgByName("USERNAME"); //取得用戶名稱string mPassword = msgServer.GetMsgByName("PASSWORD"); //取得用戶密碼msgServer.MsgTextClear(); //清除文本信息if (LoadMarkImage(mMarkName, mPassword)){//調入簽名信息mFileBody//msgServer.SetMsgByName("IMAGETYPE", mFileType); //設置簽名類型msgServer.SetMsgByName("IMAGETYPE", ".jpg"); //設置簽名類型msgServer.MsgFileBody(mFileBody); //將簽名信息打包msgServer.SetMsgByName("POSITION", "Manager"); //設置插入位置msgServer.SetMsgByName("STATUS", "打開成功!"); //設置狀態信息msgServer.MsgError(""); //清除錯誤信息}else{msgServer.MsgError("簽名或密碼錯誤!"); //設置錯誤信息}}else if (mOption.Equals("SAVESIGNATURE"))//保存簽章信息{//mRecordID = msgServer.GetMsgByName("RECORDID"); //取得文檔編號//mFileName = msgServer.GetMsgByName("FILENAME"); //取得文件名稱//mMarkName = msgServer.GetMsgByName("MARKNAME"); //取得簽名名稱//mUserName = msgServer.GetMsgByName("USERNAME"); //取得用戶名稱//mDateTime = msgServer.GetMsgByName("DATETIME"); //取得簽名時間//mHostName = Request.getRemoteAddr(); //取得用戶IP//mMarkGuid = msgServer.GetMsgByName("MARKGUID"); //取得唯一編號//msgServer.MsgTextClear(); //清除文本信息//if (SaveSignature())//{ //保存簽章信息進數據庫// msgServer.SetMsgByName("STATUS", "保存印章成功!"); //設置狀態信息// msgServer.MsgError(""); //清除錯誤信息//}//else//{// msgServer.MsgError("保存印章失敗!"); //設置錯誤信息//}}}else{msgServer.MsgError("Error:packet message");msgServer.MsgTextClear();msgServer.MsgFileClear();}Response.BinaryWrite(msgServer.MsgVariant());Response.End();}private bool LoadMarkImage(string mMarkName, object mPassword){if (Signature.HasRight(Session["userName"]+"",mPassword.ToString())){string picPath = Server.MapPath("/") + _signatureFilePath + mMarkName + ".jpg";mFileBody = File.ReadAllBytes(picPath);return true;}else{return false;}}private bool LoadMarkList(){string tMarkList = Signature.GetMaskList(); //印章列表if (tMarkList + "" != string.Empty){mMarkList = tMarkList;return true;}else{return false;}}private byte[] GetFileBody(string strFullFileName){byte[] file = new byte[0];FileInfo fInfo = new FileInfo(strFullFileName);if (fInfo.Exists == true){if ((fInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly){File.SetAttributes(strFullFileName, FileAttributes.Archive);}}file = new byte[fInfo.Length];FileStream fs = new FileStream(strFullFileName, FileMode.Open);fs.Read(file, 0, (int)fInfo.Length);fs.Close();return file;}} }服務器端主要通過iMsgServer2000對象進行同前端的交互,前端執行某些操作時(注意是某些操作,并非所有操作都同服務器端交互,具體見iWebOffice白皮書)會向后端發送一個消息,服務器端通過iMsgServer2000對象的GetMsgByName()方法可以接收參數并根據不同參數配合前端做出相應的處理。例如加載文檔時,當前端js調用WebOpen()方法時就會向服務器端傳遞一個名為"OPTION"的參數,通過這個參數可以判斷要執行的操作類型,例如此時它的值等于"LOADFILE",服務器端就可以知道是要打開一個文檔,當然此時也就知道它還會傳遞一些和打開文檔相關的參數(例如FILENAME、FILETYPE)通過這些參數,服務器端構建一個完整的文件路徑,然后調用MsgFileLoad()方法加載此文檔,這時客戶端就會打開此文檔。當然,其他還有很多類似的操作,但是原理都是一樣的,包括今天要說的電子簽章。下面先看一下文檔加載的后的截圖:
?
二、使用iWebOffice2003實現電子簽章
在iWebOffice中一個電子簽章操作包括三個交互過程,分別是:加載簽章列表(LOADMARKLIST)、加載簽章文件(LOADMARKIMAGE)、保存簽章信息(SAVESIGNATURE)。
LOADMARKLIST是加載簽章列表的過程,在這個過程中服務器端需要通過iMsgServer2000對象的SetMsgByName()方法給客戶端傳遞一個列表字符串(多個簽章中間用換行符分割)。
LOADMARKIMAGE是加載簽章文件的過程,有了簽章名稱客戶端就可以選擇相應的簽章,但是選擇了簽章名稱之后需要加載對應的簽章文件(事實上是一個圖片),加載簽章文件的過程就發生這個階段。在這個過程中服務器端的任務就是根據簽章名稱加載對應的文件,然后使用iMsgServer2000對象的MsgFileBody()方法將文件的字節流返回給客戶端。注意這個過程中客戶端需要輸入密碼,因此簽章的權限驗證部分可以在此進行處理。
SAVESIGNATURE是保存簽章信息的過程,對于簽章操作后的信息可以在此時進行保存(例如文檔編號、文件名稱、簽章名稱、簽章日期等可以在此時記錄到數據庫),在本例中由于沒有使用數據庫因此就不對簽章信息進行保存了。
這三個過程處理好之后,客戶端使用時只需要調用WebOffice對象的WebOpenSignature()方法即可調出電子簽章管理界面,下面是界面窗口:
?
通過上面的窗口可以看出,在iWebOffice中電子簽章的不僅包括印章還包括簽名、批注。從簽章列表中選擇一個簽章,然后輸入密碼,點"蓋章",此時就會從服務器端加載對應的簽章文件:
?
點擊確定就可以添加到文檔中:
?
在看兩張手寫簽名效果:
?
當然添加過簽章之后需要對文檔進行保存,不過注意文檔保存到客戶端還是服務器端,在本例中的"保存"是將文檔在服務器端進行保存,"另存為"即保存到客戶端。
總結
以上是生活随笔為你收集整理的使用iWebOffice实现电子签章的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C语言段错误-core文件
- 下一篇: Linux C 下的socket网络编程