|
来源:
https://blog.csdn.net/weixin_44385486/article/details/126481493
一、前言
今天公司领导提出一个功能,说实现一个文件的签字+盖章功能,然后自己进行了简单的学习,对文档进行数字签名与签署纸质文档的原因大致相同,数字签名通过使用计算机加密来验证 (身份验证:验证人员和产品所声明的身份是否属实的过程。例如,通过验证用于签名代码的数字签名来确认软件发行商的代码来源和完整性。)数字信息,如文档、电子邮件和宏。数字签名有助于确保:真实性,完整性,不可否认性。目前市面上的电子签章产品也是多样化,但是不管是哪个厂家的产品,在线签章简单易用,同时也能保证签章的有效性,防篡改,防伪造,稳定,可靠就是好产品。
此次开源的系统模拟演示了文件在OA系统中的流转,主要为办公系统跨平台在线处理Office文档提供了完美的解决方案。Word文档在线处理的核心环节,包括:起草文档、领导审批、核稿、领导盖章、正式发文。PageOffice产品支持PC端Word文档在线处理的所有环节;MobOffice产品支持了移动端领导审批和领导盖章的功能。支持PC端和移动端对文档审批和盖章的互认。然后此次博客中使用的卓正软件的电子签章采用自主知识产权的核心智能识别验证技术,确保文档安全可靠。采用 COM、ActiveX嵌入式技术开发,确保软件能够支持多种应用。遵循《中华人民共和国电子签名法》关于电子签名的规范,同时支持国际通用的 RSA算法,符合国家安全标准。
PageOffice和MobOffice产品结合使用为跨平台处理Office文件提供了完美的解决方案,主要功能有word在线编辑保存和留痕,word和pdf文件在线盖章(电子印章)。
二、项目源码及部署
1、项目结构及使用框架
该签字+盖章流程系统使用了SpringBoot+thymeleaf实现的,然后jar包依赖使用了maven

@Controller@RequestMapping("/mobile")publicclassMobileOfficeController{@Value("${docpath}")privateStringdocPath;@Value("${moblicpath}")privateStringmoblicpath;@AutowiredDocServicem_docService;/***添加MobOffice的服务器端授权程序Servlet(必须)**/@RequestMapping("/opendoc")publicvoidopendoc(HttpServletRequestrequest,HttpServletResponseresponse,HttpSessionsession,Stringtype,StringuserName)throwsException{StringfileName="";userName=URLDecoder.decode(userName,"utf-8");Docdoc=m_docService.getDocById(1);if(type.equals("word")){fileName=doc.getDocName();}else{fileName=doc.getPdfName();}OpenModeTypeopenModeType=OpenModeType.docNormalEdit;if(fileName.endsWith(".doc")){openModeType=OpenModeType.docNormalEdit;}elseif(fileName.endsWith(".pdf")){Stringmode=request.getParameter("mode");if(mode.equals("normal")){openModeType=OpenModeType.pdfNormal;}else{openModeType=OpenModeType.pdfReadOnly;}}MobOfficeCtrlmobCtrl=newMobOfficeCtrl(request,response);mobCtrl.setSysPath(moblicpath);mobCtrl.setServerPage("/mobserver.zz");//mobCtrl.setZoomSealServer("http://xxx.xxx.xxx.xxx:8080/ZoomSealEnt/enserver.zz");mobCtrl.setSaveFilePage("/mobile/savedoc?testid="+Math.random());mobCtrl.webOpen("file://"+docPath+fileName,openModeType,userName);}@RequestMapping("/savedoc")publicvoidsavedoc(HttpServletRequestrequest,HttpServletResponseresponse){FileSaverfs=newFileSaver(request,response);fs.saveToFile(docPath+fs.getFileName());fs.close();}}
@ServicepublicclassDocServiceImplimplementsDocService{@AutowiredDocMapperdocMapper;@OverridepublicDocgetDocById(intid)throwsException{Docdoc=docMapper.getDocById(id);//如果doc为null的话,页面所有doc.属性都报错if(doc==null){doc=newDoc();}returndoc;}@OverridepublicIntegeraddDoc(Docdoc)throwsException{intid=docMapper.addDoc(doc);returnid;}@OverridepublicIntegerupdateStatusForDocById(Docdoc)throwsException{intid=docMapper.updateStatusForDocById(doc);returnid;}@OverridepublicIntegerupdateDocNameForDocById(Docdoc)throwsException{intid=docMapper.updateDocNameForDocById(doc);returnid;}@OverridepublicIntegerupdatePdfNameForDocById(Docdoc)throwsException{intid=docMapper.updatePdfNameForDocById(doc);returnid;}}
publicclassCopyFileUtil{//拷贝文件publicstaticbooleancopyFile(StringoldPath,StringnewPath)throwsException{booleancopyStatus=false;intbytesum=0;intbyteread=0;Fileoldfile=newFile(oldPath);if(oldfile.exists()){//文件存在时InputStreaminStream=newFileInputStream(oldPath);//读入原文件FileOutputStreamfs=newFileOutputStream(newPath);byte[]buffer=newbyte[1444];intlength;while((byteread=inStream.read(buffer))!=-1){bytesum+=byteread;//字节数文件大小//System.out.println(bytesum);fs.write(buffer,0,byteread);}fs.close();inStream.close();copyStatus=true;}else{copyStatus=false;}returncopyStatus;}}
publicclassQRCodeUtil{privateStringcodeText;//二维码内容privateBarcodeFormatbarcodeFormat;//二维码类型privateintwidth;//图片宽度privateintheight;//图片高度privateStringimageformat;//图片格式privateintbackColorRGB;//背景色,颜色RGB的数值既可以用十进制表示,也可以用十六进制表示privateintcodeColorRGB;//二维码颜色privateErrorCorrectionLevelerrorCorrectionLevel;//二维码纠错能力privateStringencodeType;publicQRCodeUtil(){codeText=&#34;www.zhuozhengsoft.com&#34;;barcodeFormat=BarcodeFormat.PDF_417;width=400;height=400;imageformat=&#34;png&#34;;backColorRGB=0xFFFFFFFF;codeColorRGB=0xFF000000;errorCorrectionLevel=ErrorCorrectionLevel.H;encodeType=&#34;UTF-8&#34;;}publicQRCodeUtil(Stringtext){codeText=text;barcodeFormat=BarcodeFormat.PDF_417;width=400;height=400;imageformat=&#34;png&#34;;backColorRGB=0xFFFFFFFF;codeColorRGB=0xFF000000;errorCorrectionLevel=ErrorCorrectionLevel.H;encodeType=&#34;UTF-8&#34;;}publicStringgetCodeText(){returncodeText;}publicvoidsetCodeText(StringcodeText){this.codeText=codeText;}publicBarcodeFormatgetBarcodeFormat(){returnbarcodeFormat;}publicvoidsetBarcodeFormat(BarcodeFormatbarcodeFormat){this.barcodeFormat=barcodeFormat;}publicintgetWidth(){returnwidth;}publicvoidsetWidth(intwidth){this.width=width;}publicintgetHeight(){returnheight;}publicvoidsetHeight(intheight){this.height=height;}publicStringgetImageformat(){returnimageformat;}publicvoidsetImageformat(Stringimageformat){this.imageformat=imageformat;}publicintgetBackColorRGB(){returnbackColorRGB;}publicvoidsetBackColorRGB(intbackColorRGB){this.backColorRGB=backColorRGB;}publicintgetCodeColorRGB(){returncodeColorRGB;}publicvoidsetCodeColorRGB(intcodeColorRGB){this.codeColorRGB=codeColorRGB;}publicErrorCorrectionLevelgetErrorCorrectionLevel(){returnerrorCorrectionLevel;}publicvoidsetErrorCorrectionLevel(ErrorCorrectionLevelerrorCorrectionLevel){this.errorCorrectionLevel=errorCorrectionLevel;}privateBufferedImagetoBufferedImage(BitMatrixbitMatrix){intwidth=bitMatrix.getWidth();intheight=bitMatrix.getHeight();BufferedImageimage=newBufferedImage(width,height,BufferedImage.TYPE_INT_RGB);for(intx=0;x<width;x++){for(inty=0;y<height;y++){image.setRGB(x,y,bitMatrix.get(x,y)?this.codeColorRGB:this.backColorRGB);}}returnimage;}privatebyte[]writeToBytes(BitMatrixbitMatrix)throwsIOException{try{BufferedImagebufferedimage=toBufferedImage(bitMatrix);//将图片保存到临时路径中Filefile=java.io.File.createTempFile(&#34;~pic&#34;,&#34;.&#34;+this.imageformat);//System.out.println(&#34;临时图片路径:&#34;+file.getPath());ImageIO.write(bufferedimage,this.imageformat,file);//获取图片转换成的二进制数组FileInputStreamfis=newFileInputStream(file);intfileSize=fis.available();byte[]imageBytes=newbyte[fileSize];fis.read(imageBytes);fis.close();//删除临时文件if(file.exists()){file.delete();}returnimageBytes;}catch(Exceptione){System.out.println(&#34;Imageerr:&#34;+e.getMessage());returnnull;}}//获取二维码图片的字节数组publicbyte[]getQRCodeBytes()throwsIOException{try{MultiFormatWritermultiFormatWriter=newMultiFormatWriter();//设置二维码参数Maphints=newHashMap();if(this.errorCorrectionLevel!=null){//设置二维码的纠错级别hints.put(EncodeHintType.ERROR_CORRECTION,this.errorCorrectionLevel);}if(this.encodeType!=null&&this.encodeType.trim().length()>0){//设置编码方式hints.put(EncodeHintType.CHARACTER_SET,this.encodeType);}BitMatrixbitMatrix=multiFormatWriter.encode(this.codeText,BarcodeFormat.QR_CODE,this.width,this.height,hints);byte[]bytes=writeToBytes(bitMatrix);returnbytes;}catch(Exceptione){e.printStackTrace();returnnull;}}}2、项目下载及部署
- 项目源码加我微信:xttblog2,回复我“盖章系统”发送给你
- 下载项目源码后,使用idea导入slndemo项目并运行

- 将项目slndemo下的slndemodata.zip压缩包拷贝到本地D盘根目录下并解压


三、功能展示
1、项目启动后登录首页
- 项目地址:http://localhost:8888/pc/login
- 账户:张三 密码:123456

2、系统首页功能简介
这是一个简单的Demo项目,模拟Word文件在办公系统中的主要流转环节,并不意味着PageOffice产品只能支持这样的文档处理流程。PageOffice产品只提供文档在线处理的功能,包括:打开、编辑、保存、动态填充、文档合并、套红、留痕、盖章等上百项功能(详细请参考PageOffice产品开发包中的示例),不提供流程控制功能,所以不管开发什么样的Web系统,只要是需要在线处理Office文档,都可以根据自己的项目需要,调用PageOffice产品相应的功能即可。「注意:为了简化代码逻辑,此演示程序只能创建一个文档进行流转。」

3、点击起草文档

- 点击代办文档,然后点击编辑,当你点击编辑时你没有下载PageOffice,他会提醒你安装,你点击安装之后,关闭浏览器,重新打开浏览器就能编辑了!

- 我们使用了PageOffice企业版,必须要注册序列化
- 版 本:PageOffice企业版5(试用)
- 序列号:35N8V-2YUC-LY77-W14XL

- 当我们注册成功以后,就可以编辑发布的文件或者公告了



4、审批




5、审稿



6、盖章和签字的实现




- 正确的账户密码是:
- 账户:王五
- 密码:123456





7、完整签字盖章文件



其他优质好项目仿百度网盘的一款轻量级微服务架构网盘系统SpringBoot+Vue.Js搭建图书管理系统开源项目基于 Vue3.0+ElementPlus 后台精简模板分享70套 Java 项目+实战课Java项目精选读者群正式开发,先到先得!欢迎添加编程君个人微信 cxycode666 进粉丝群或围观朋友 |
|