600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > java 实现生成公司的电子公章 并且盖章生成电子合同

java 实现生成公司的电子公章 并且盖章生成电子合同

时间:2019-02-09 06:59:44

相关推荐

java 实现生成公司的电子公章 并且盖章生成电子合同

前言

以下方法大多数是博主从网上查阅资料参考很多大神的方法之后,然后结合博主的理解,将大神们的方法整理实现的,还有不少方法忘记参考的哪位大佬的了,所以目前仅是将想起来的大神提供出来,如有侵权请联系博主删除。未经博主同意,暂不给转载哈。以下出现的公司名称原本是博主的公司,现在已注销了,如有侵权请联系博主删除。

参考大佬们的代码:(部分)

JAVA利用Graphics2D生成电子签章

修改Jar包中的内容(替换、删除文件)+ aspose-words签名解除 + 配置maven引入

一、生成电子公章工具类

电子公章效果如图:

工具类如下:(直接拷贝可用,已根据博主需要做了一下细微调整)

package com.siboo.util;import java.awt.BasicStroke;import java.awt.Color;import java.awt.Font;import java.awt.Graphics2D;import java.awt.RenderingHints;import java.awt.Transparency;import java.awt.font.FontRenderContext;import java.awt.geom.AffineTransform;import java.awt.geom.Ellipse2D;import java.awt.geom.Rectangle2D;import java.awt.image.BufferedImage;import com.newtec.myqdp.server.utils.StringUtils;public class Graphics2DUtil {private static final int WIDTH = 450;//图片宽度private static final int HEIGHT = 450;//图片高度/*** * @Title: splitImage* @Description: 分割图片* @param image 图片BufferedImage流* @param rows 分割行* @param cols 分割列* @return BufferedImage[] 返回分割后的图片流*/public static BufferedImage[] splitImage(BufferedImage image, int rows, int cols) {// 分割成4*4(16)个小图int chunks = rows * cols;// 计算每个小图的宽度和高度int chunkWidth = image.getWidth() / cols + 3;// 向右移动3int chunkHeight = image.getHeight() / rows;int count = 0;BufferedImage[] imgs = new BufferedImage[chunks];for (int x = 0; x < rows; x++) {for (int y = 0; y < cols; y++) {//设置小图的大小和类型imgs[count] = new BufferedImage(chunkWidth, chunkHeight, BufferedImage.TYPE_INT_RGB);//写入图像内容Graphics2D gr = imgs[count].createGraphics();// 增加下面代码使得背景透明 imgs[count] = gr.getDeviceConfiguration().createCompatibleImage(chunkWidth, chunkHeight, Transparency.TRANSLUCENT);//gr.setBackground(Color.WHITE);// 背景为白色// // 加上这句才算真正将背景颜色设置为透明色//gr.clearRect(0, 0,chunkWidth,chunkHeight);gr.dispose();gr = imgs[count].createGraphics();gr.drawImage(image, 0, 0,chunkWidth, chunkHeight,chunkWidth * y, chunkHeight * x,chunkWidth * y + chunkWidth,chunkHeight * x + chunkHeight, null);gr.dispose();count++;}}return imgs;}/*** * @Title: startGraphics2D* @Description: 生成公司电子公章* @param message 公司名称* @param centerName 公章类型,如:测试章* @param year 时间* @return BufferedImage 返回类型*/public static BufferedImage startGraphics2D(String message, String centerName, String year){// 定义图像buffer BufferedImage buffImg = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); Graphics2D g = buffImg.createGraphics(); // 增加下面代码使得背景透明 buffImg = g.getDeviceConfiguration().createCompatibleImage(WIDTH, HEIGHT, Transparency.TRANSLUCENT); g.dispose(); g = buffImg.createGraphics(); // 背景透明代码结束 g.setColor(Color.RED);//设置锯齿圆滑g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);//绘制圆int radius = HEIGHT/3;//周半径int CENTERX = WIDTH/2;//画图所出位置int CENTERY = HEIGHT/2;//画图所处位置Ellipse2D circle = new Ellipse2D.Double();circle.setFrameFromCenter(CENTERX, CENTERY, CENTERX + radius, CENTERY + radius);g.setStroke(new BasicStroke(10));//设置圆的宽度g.draw(circle);int num = 120;int num1 = 40;// num = 90;num1 = 72;//绘制中间的五角星g.setFont(new Font("宋体", Font.BOLD, num));g.drawString("★", CENTERX-(num/2), CENTERY+(num/3)); //添加姓名g.setFont(new Font("宋体", Font.LAYOUT_LEFT_TO_RIGHT, 30));// 写入签名g.drawString(centerName, CENTERX -(num1), CENTERY +(30+50));//添加年份g.setFont(new Font("宋体", Font.LAYOUT_LEFT_TO_RIGHT, 20));// 写入签名g.drawString(year, CENTERX -(66), CENTERY +(30+78));//根据输入字符串得到字符数组char[] messages = message.toCharArray();//输入的字数int ilength = messages.length;//设置字体属性int fontsize = 40;Font f = new Font("Serif", Font.BOLD, fontsize);FontRenderContext context = g.getFontRenderContext();Rectangle2D bounds = f.getStringBounds(message, context);//字符宽度=字符串长度/字符数double char_interval = (bounds.getWidth() / ilength);//上坡度double ascent = -bounds.getY() + 3;int first = 0,second = 0;boolean odd = false;if (ilength%2 == 1) {first = (ilength-1)/2;odd = true;} else {first = (ilength)/2-1;second = (ilength)/2;odd = false;}double radius2 = radius - ascent;double x0 = CENTERX;double y0 = CENTERY - radius + ascent;//旋转角度double a = 2*Math.asin(char_interval/(2*radius2));if (odd) {g.setFont(f);g.drawString(StringUtils.toString(messages[first]), (float)(x0 - char_interval/2), (float)y0);//中心点的右边for (int i=first+1;i<ilength;i++){double aa = (i - first) * a;double ax = radius2 * Math.sin(aa);double ay = radius2 - radius2 * Math.cos(aa);AffineTransform transform = AffineTransform.getRotateInstance(aa);//,x0 + ax, y0 + ay);Font f2 = f.deriveFont(transform);g.setFont(f2);g.drawString(StringUtils.toString(messages[i]), (float)(x0 + ax - char_interval/2* Math.cos(aa)), (float)(y0 + ay - char_interval/2* Math.sin(aa)));}//中心点的左边for (int i=first-1;i>-1;i--){double aa = (first - i) * a;double ax = radius2 * Math.sin(aa);double ay = radius2 - radius2 * Math.cos(aa);AffineTransform transform = AffineTransform.getRotateInstance(-aa);//,x0 + ax, y0 + ay);Font f2 = f.deriveFont(transform);g.setFont(f2);g.drawString(StringUtils.toString(messages[i]), (float)(x0 - ax - char_interval/2* Math.cos(aa)), (float)(y0 + ay + char_interval/2* Math.sin(aa)));}} else {//中心点的右边for (int i=second;i<ilength;i++){double aa = (i - second + 0.5) * a;double ax = radius2 * Math.sin(aa);double ay = radius2 - radius2 * Math.cos(aa);AffineTransform transform = AffineTransform.getRotateInstance(aa);//,x0 + ax, y0 + ay);Font f2 = f.deriveFont(transform);g.setFont(f2);g.drawString(StringUtils.toString(messages[i]), (float)(x0 + ax - char_interval/2* Math.cos(aa)), (float)(y0 + ay - char_interval/2* Math.sin(aa)));}//中心点的左边for (int i=first;i>-1;i--){double aa = (first - i + 0.5) * a;double ax = radius2 * Math.sin(aa);double ay = radius2 - radius2 * Math.cos(aa);AffineTransform transform = AffineTransform.getRotateInstance(-aa);//,x0 + ax, y0 + ay);Font f2 = f.deriveFont(transform);g.setFont(f2);g.drawString(StringUtils.toString(messages[i]), (float)(x0 - ax - char_interval/2* Math.cos(aa)), (float)(y0 + ay + char_interval/2* Math.sin(aa)));}}return buffImg;}}

调用方法如下:

public static void main(String[] args) throws Exception{Date dNow = new Date( );SimpleDateFormat ft = new SimpleDateFormat ("yyyy年MM月dd日");String year = ft.format(dNow);BufferedImage image = startGraphics2D("广州思博商贸有限公司","合同专用章",year);String filePath = "";try {filePath = "F:\\BaiduNetdiskDownload\\"+new Date().getTime()+".png";ImageIO.write(image, "png", new File(filePath)); //将其保存在D:\\下,得有这个目录} catch (Exception ex) {ex.printStackTrace();}}

二、由word模板生成电子合同PDF文件,并盖章

1.对word文档操作的工具类如下:

package com.siboo.util;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.util.Iterator;import java.util.List;import java.util.Map;import org.apache.poi.xwpf.usermodel.XWPFDocument;import org.apache.poi.xwpf.usermodel.XWPFParagraph;import org.apache.poi.xwpf.usermodel.XWPFRun;import org.apache.poi.xwpf.usermodel.XWPFTable;import org.apache.poi.xwpf.usermodel.XWPFTableCell;import org.apache.poi.xwpf.usermodel.XWPFTableRow;import com.aspose.words.License;import com.newtec.myqdp.server.utils.StringUtils;public class WordUtil {/*** * @Title: replaceAndGenerateWord* @Description: 替换word中需要替换的特殊字符* 优化后是为了分别减少map遍历,增加性能,前提是表格的替换的数据不一样,所以将两者分离处理(加空间,提性能)* @param srcPath 需要替换的文档全路径* @param destPath 替换后文档的保存路径* @param contentMap {key:将要被替换的内容,value:替换后的内容}* @param replaceTableMap {key:将要被替换的表格内容,value:替换后的表格内容}* @return boolean 返回成功状态*/public static boolean replaceAndGenerateWord(String srcPath, String exportFile, Map<String, String> contentMap, Map<String, String> replaceTableMap) {boolean bool = true;try {FileInputStream inputStream = new FileInputStream(srcPath);XWPFDocument document = new XWPFDocument(inputStream);// 替换段落中的指定文字Iterator<XWPFParagraph> itPara = document.getParagraphsIterator();while (itPara.hasNext()) {XWPFParagraph paragraph = itPara.next();commonCode(paragraph, contentMap);}// 替换表格中的指定文字Iterator<XWPFTable> itTable = document.getTablesIterator();while (itTable.hasNext()) {XWPFTable table = itTable.next();int rcount = table.getNumberOfRows();for (int i = 0; i < rcount; i++) {XWPFTableRow row = table.getRow(i);List<XWPFTableCell> cells = row.getTableCells();for (XWPFTableCell cell : cells) {//单元格中有段落,得做段落处理List<XWPFParagraph> paragraphs = cell.getParagraphs();for (XWPFParagraph paragraph : paragraphs) {commonCode(paragraph, replaceTableMap);}}}}FileOutputStream outStream = new FileOutputStream(exportFile);document.write(outStream);outStream.close();inputStream.close();}catch (Exception e){bool = false;e.printStackTrace();}return bool;}/*** * @Title: commonCode* @Description: 替换内容* @param paragraph 被替换的文本信息* @param contentMap {key:将要被替换的内容,value:替换后的内容}*/private static void commonCode(XWPFParagraph paragraph,Map<String, String> contentMap){List<XWPFRun> runs = paragraph.getRuns();for (XWPFRun run : runs) {String oneparaString = run.getText(run.getTextPosition());if (StringUtils.isStrNull(oneparaString)){continue;}for (Map.Entry<String, String> entry : contentMap.entrySet()) {oneparaString = oneparaString.replace(entry.getKey(), StringUtils.isStrNull(entry.getValue()) ? "--" : entry.getValue());}run.setText(oneparaString, 0);}}/*** * @Title: getLicense* @Description:验证license许可凭证* @return boolean 返回验证License状态*/private static boolean getLicense() {boolean result = true;try {// new License().setLicense(new FileInputStream(new File("D:\\develop\\template\\license.xml").getAbsolutePath()));new License().setLicense(new FileInputStream(new File(FilesUtil.getLicensePath()).getAbsolutePath()));} catch (Exception e) {result = false;e.printStackTrace();}return result;}/*** * @Title: wordConverterToPdf* @Description: word转pdf(aspose转换)* @param wordPath word 全路径,包括文件全称* @param pdfPath pdf 保存路径,包括文件全称* @return boolean 返回转换状态*/public static boolean wordConverterToPdf(String wordPath, String pdfPath) {System.out.println("===================aspose开始转换=======================");//开始时间long start = System.currentTimeMillis();boolean bool = false;// 验证License,若不验证则转化出的pdf文档会有水印产生if (!getLicense()) return bool;try {FileOutputStream os = new FileOutputStream(new File(pdfPath));// 新建一个pdf文档输出流com.aspose.words.Document doc = new com.aspose.words.Document(wordPath);// Address是将要被转化的word文档doc.save(os, com.aspose.words.SaveFormat.PDF);// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换os.close();bool = true;} catch (Exception e) {e.printStackTrace();} finally {System.out.println("(aspose)word转换PDF完成,用时"+(System.currentTimeMillis()-start)/1000.0+"秒");}return bool;}/*** * @Title: wordConverterToPdfJacob* @Description: word转pdf(jacob转换)* @param wordFile word 全路径,包括文件全称* @param pdfFile pdf 保存路径,包括文件全称* @return boolean 返回转换状态*/// public static boolean wordConverterToPdfJacob(String wordFile, String pdfFile) {//System.out.println("===================jacob开始转换=======================");////开始时间//long start = System.currentTimeMillis(); //ActiveXComponent app = new ActiveXComponent("Word.Application");// 创建对象,花了很长时间//boolean bool = false;//try {//// 打开word//// 获得word中所有打开的文档//Dispatch documents = app.getProperty("Documents").toDispatch();System.out.println("打开文件: " + wordFile);//// 打开文档//Dispatch document = Dispatch.call(documents, "Open", wordFile, false, true).toDispatch();//// 如果文件存在的话,不会覆盖,会直接报错,所以我们需要判断文件是否存在//File target = new File(pdfFile);//if (target.exists()) {//target.delete();//}System.out.println("另存为: " + pdfFile);//Dispatch.call(document, "SaveAs", pdfFile, 17);//// 关闭文档//Dispatch.call(document, "Close", false);//bool = true;//} catch (Exception e) {//System.out.println("转换失败" + e.getMessage());//} finally {//// 关闭office//app.invoke("Quit", 0);//System.out.println("生成完成,用时"+(System.currentTimeMillis()-start)/1000.0+"秒");//}//return bool;// }/*** * @Title: insertRow* @Description: 在word表格中指定位置插入一行,并将某一行的样式复制到新增行* @param table 需要插入的表格* @param copyrowIndex 需要复制的行位置* @param newrowIndex 需要新增一行的位置* @return void 返回类型*/public static void insertRow(XWPFTable table, int copyrowIndex, int newrowIndex) {// 在表格中指定的位置新增一行XWPFTableRow targetRow = table.insertNewTableRow(newrowIndex);// 获取需要复制行对象XWPFTableRow copyRow = table.getRow(copyrowIndex);//复制行对象targetRow.getCtRow().setTrPr(copyRow.getCtRow().getTrPr());//或许需要复制的行的列List<XWPFTableCell> copyCells = copyRow.getTableCells();//复制列对象XWPFTableCell targetCell = null;for (int i = 0; i < copyCells.size(); i++) {XWPFTableCell copyCell = copyCells.get(i);targetCell = targetRow.addNewTableCell();targetCell.getCTTc().setTcPr(copyCell.getCTTc().getTcPr());if (copyCell.getParagraphs() != null && copyCell.getParagraphs().size() > 0) {targetCell.getParagraphs().get(0).getCTP().setPPr(copyCell.getParagraphs().get(0).getCTP().getPPr());if (copyCell.getParagraphs().get(0).getRuns() != null&& copyCell.getParagraphs().get(0).getRuns().size() > 0) {XWPFRun cellR = targetCell.getParagraphs().get(0).createRun();cellR.setBold(copyCell.getParagraphs().get(0).getRuns().get(0).isBold());} } }}}

2.生成电子合同

String id = "?";// 合同id,根据自己需求// 合同保存路径String contractPath = FilesUtil.getContract();// 电子合同临时保存路径StringBuilder temporaryPath = new StringBuilder(contractPath).append("temporary");// 判断临时文件夹是否存在,不存在则新建File file = new File(temporaryPath.toString());if (!file.exists()) {file.mkdirs();}temporaryPath.append(File.separator).append(id).append(".docx");// 1、 查询合同信息(该方法省略,具体看自己的需求)Map<String, String> replaceMap = getContractData(contractService,id, temporaryPath.toString());String userNum = replaceMap.get("userNum");StringBuilder destPathDOCX = new StringBuilder(contractPath).append(userNum);// 判断用户文件夹是否存在,不存在则新建File userNumFile = new File(destPathDOCX.toString());if (!userNumFile.exists()) {userNumFile.mkdirs();}destPathDOCX.append(File.separator).append(id).append(".docx");//StringBuilder savePath = new StringBuilder(userNum)//.append(File.separator).append(id).append(".pdf");Map<String, String> replaceTableMap = new HashMap<String, String>();replaceTableMap.put("totalAmount", replaceMap.remove("totalAmount"));replaceTableMap.put("totalCapitalizeAmount", replaceMap.remove("totalCapitalizeAmount"));// 2、 替换合同里面的参数WordUtil.replaceAndGenerateWord(temporaryPath.toString(), destPathDOCX.toString(), replaceMap, replaceTableMap);StringBuilder pdfFile = new StringBuilder(contractPath).append(userNum).append(File.separator).append(id).append(".pdf");// 3、将word转pdf文件Boolean bool = WordUtil.wordConverterToPdf(destPathDOCX.toString(), pdfFile.toString());if (!bool) {map.put("msg", "合同word转pdf文件失败");return;}// 4.1 删除临时电子合同File temporaryPathDOCX = new File(temporaryPath.toString());if (temporaryPathDOCX.exists()) {temporaryPathDOCX.delete();}// 4.2 删除word电子合同File fileDOCX = new File(destPathDOCX.toString());if (fileDOCX.exists()) {fileDOCX.delete();}

电子合同效果(pdf文件)

3.电子合同盖章

/*** * @Title: itextPDFAddPicture* @Description: 为pdf加图片(电子合同盖公章)* @param inputStream 电子合同pdf文件流* @param map {company:公司公章名称,purpose:公章用途,year:日期}* @param targetPath 保存路径* @throws Exception 异常参数*/public static void itextPDFAddPicture(InputStream inputStream, Map<String, String> map, String targetPath) throws Exception{// 1.1 读取模板文件PdfReader reader = new PdfReader(inputStream);// 1.2 创建文件输出流FileOutputStream out = new FileOutputStream(targetPath);// 2、创建PdfStamper对象PdfStamper stamper = new PdfStamper(reader, out);// 3、设置公章信息String company = FilesUtil.getDefaultCompany();// 公司公章名称String purpose = FilesUtil.getDefaultPurpose();// 公章用途String year = map.get("year");// 日期if (StringUtils.isStrNull(year)) {year = new SimpleDateFormat (FilesUtil.getContractTimeFormat()).format(new Date());}// 4、生成公章BufferedImage bufferedImage = Graphics2DUtil.startGraphics2D(company, purpose, year);// 整个公章图片流BufferedImage[] imgs = Graphics2DUtil.splitImage(bufferedImage, 1, 2);BufferedImage leftBufferedImage = imgs[0];// 左边公章图片流BufferedImage rightBufferedImage = imgs[1];// 右边公章图片流// 5、读公章图片Image image = Image.getInstance(imageToBytes(bufferedImage));Image leftImage = Image.getInstance(imageToBytes(leftBufferedImage));Image rightImage = Image.getInstance(imageToBytes(rightBufferedImage));int chunkWidth = 200;// 公章大小,x轴int chunkHeight = 200;// 公章大小,y轴// 获取pdf页面的高和宽Rectangle pageSize = reader.getPageSize(1);float height = pageSize.getHeight();float width = pageSize.getWidth();// 6、为pdf每页加印章// 设置公章的位置float xL = width - chunkWidth/2 - 2;float yL = height/2-chunkHeight/2-25;float xR = width-chunkHeight/2 + chunkHeight/8 + 4;float yR = yL;// 6.1 第一页盖左章leftImage.scaleToFit(chunkWidth, chunkHeight);// 公章大小leftImage.setAbsolutePosition(xL, yL);// 公章位置// 6.2 第二页盖右章rightImage.scaleToFit(chunkWidth, chunkHeight);// 公章大小rightImage.setAbsolutePosition(xR, yR);// 公章位置int pdfPages = reader.getNumberOfPages();// pdf页面页码// 遍历为每页盖左章或右章for (int i = 1; i <= pdfPages; i++) {if (i % 2 == 0) {// 盖右章stamper.getOverContent(i).addImage(rightImage);} else {// 盖左章stamper.getOverContent(i).addImage(leftImage);}}// 6.3 最后一页盖公章image.scaleToFit(chunkWidth, chunkWidth);image.setAbsolutePosition(width/2 + 32, height-chunkHeight + 20);stamper.getOverContent(pdfPages).addImage(image);// 7、关闭相关流stamper.close();out.close();reader.close();inputStream.close();}

盖章效果如下:

4.补充

配置文件:

license.xml

<License><Data><Products><Product>Aspose.Total for Java</Product><Product>Aspose.Words for Java</Product></Products><EditionType>Enterprise</EditionType><SubscriptionExpiry>20991231</SubscriptionExpiry><LicenseExpiry>20991231</LicenseExpiry><SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber></Data><Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature></License>

合同模板.docx

所需相关jar包

链接:/s/12ysaXaJ0XfRj4MUXwaIUXA

提取码:ar8a

总结

此贴是博主第一次写博,还存在很多不足之处,后期会慢慢完善,如果有不理解之处可以联系博主哈,也欢迎各路大神过来一起探讨。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。