前几年认为信息化办公发展的子方向:“图纸电子签章”会很有前景,也是单位信息化管理急需的管理方式,随之进行了电子签章的相关研究与开发,虽然前期投入大量的时间与精力,但后期受时间与精力的各种限制,图纸的电子签章系统未能开发完,并且搁置。系统虽未完成,但系统核心算法及电子签章的核心功能部分均已实现,现将个人的相关研究成果无偿与大家分享。
一、系统介绍
一图胜千言,已实现的系统结构图如下:
功能界面:
上传未签字电子图;
上传系统程序界面,支持多个图纸上传;
3、上传合规的电子图会自动生成一份MAKE签字图;
4、电签后的电子图;
二、技术部分
1、开发使用Python语言,django框架;
2、PDF读取解析使用了Pdfminer、PyPDF2、Reportlab;
3、核心算法及实现功能代码
(1)、PDF处理代码
def readpdf(filename): try: fp = open( filename, 'rb') #创建一个PDF文档解析器对象 parser = PDFParser(fp) #创建一个PDF文档对象存储文档结构 #提供密码初始化,没有就不用传该参数 #document = PDFDocument(parser, password) document = PDFDocument(parser) #检查文件是否允许文本提取 if not document.is_extractable: raise PDFTextExtractionNotAllowed #创建一个PDF资源管理器对象来存储共享资源 #caching = False不缓存 rsrcmgr = PDFResourceManager(caching = False) # 创建一个PDF设备对象 laparams = LAParams() # 创建一个PDF页面聚合对象 device = PDFPageAggregator(rsrcmgr, laparams=laparams) #创建一个PDF解析器对象 interpreter = PDFPageInterpreter(rsrcmgr, device) #处理文档当中的每个页面 # 循环遍历列表,每次处理一个page的内容 for page in PDFPage.create_pages(document): interpreter.process_page(page) bztklisk=BZTK.objects.all() for danxiang in bztklisk: if tuplePK(ast.literal_eval(danxiang.CC), page.mediabox) and str(page.rotate) == danxiang.Qt:#判断是否为图框及类型 layout=device.get_result() # 这里layout是一个LTPage对象 里面存放着 这个page解析出的各种对象 for x in layout: #如果x是水平文本对象的话 if(isinstance(x.bbox,tuple)): print('X') if tuplePK(ast.literal_eval(danxiang.JCW), x.bbox) and x.get_text()[0:1] == danxiang.TZ:#是否院里图签标识确认 print('-------------so easy---------------') fp.close() makerun(filename) #合规的电子图运行电子签 # debug(x.analyze()) except IOError as err: print('File error:' + str(err)) finally: fp.close()
(2)、图框检测代码
def tuplePK(pka, pkb): #校验图框 print(pka) print(pkb) if abs(pka[0]-pkb[0])<2 :#允许PDF图框误差值 if abs(pka[1]-pkb[1])<2 : if abs(pka[2] - pkb[2]) < 2: if abs(pka[3] - pkb[3]) < 2: return True print('false') return False
(3)、电子签代码
def makerun(filename):#运行加载PDF文件 canvas_data = get_overlay_canvas() merge(canvas_data, template_path=filename)def get_overlay_canvas() -> io.BytesIO: data = io.BytesIO()#签名图片处理及放置位置 pdf = canvas.Canvas(data) pic_line_file = os.path.join(os.path.dirname(__file__), 'fileZ.png') pdf.drawImage( pic_line_file, 60, 200, width=66, height=110, mask=[255, 255, 255, 255, 255, 255]) pic_line_file = os.path.join(os.path.dirname(__file__), 'fileSQ.png') pdf.drawImage(pic_line_file, 30, 595, width=25, height=40, mask=[255, 255, 255, 255, 255, 255]) # pdf.drawString(x=33, y=55, text='Willi222222222222222222222222222222222222222222222222222s') # pdf.drawString(x=14, y=55, text='Jo222222222222222222222222222222222222222222222222222hn') pdf.save() data.seek(0) return datadef merge(overlay_canvas: io.BytesIO, template_path: str) -> io.BytesIO: with open(template_path, "rb") as inFile:#读取PDF original = pypdf.PdfFileReader(inFile) background = original.getPage(0) foreground = pypdf.PdfFileReader(overlay_canvas).getPage(0) #加载电子签数据流 # merge the first two pages background.mergePage(foreground) # add all pages to a writer writer = pypdf.PdfFileWriter()#写入整合数据流 for i...