java使用poi、itextpdf将word、ppt转为pdf文件,并对pdf文件加盖签章 |
您所在的位置:网站首页 › ppt转换pdf文档 › java使用poi、itextpdf将word、ppt转为pdf文件,并对pdf文件加盖签章 |
1 环境及背景
SpringBoot项目,使用poi、itextpdf将excel、ppt、word文件转为pdf,并对pdf文件进行签章; 对Excel文件加图片水印,并加密设置为只读。 下面的方法都是返回的byte数组,可视具体情况直接将文件输出。 office文件分为2003跟2007版本,所以处理的方法回有所区别。 还有很多其他方式可以实现转pdf,例如可以用第三方插件aspose处理office文件,但是需要收费; 可以使用spire,也是收费的; 还可以使用OpenOffice办公组件,加org.jodconverter,组件是适用于Linux,windows的。 2 pdf文件加盖签章数字证书生成: keytool -storepass 123456 -genkeypair -keyalg RSA -keysize 1024 -sigalg SHA1withRSA -validity 3650 -alias mycert -keystore my.keystore -dname "CN=www.sample.com, OU=sample, O=sample, L=BJ, ST=BJ, C=CN" 打开cmd窗口直接执行上面命令即可,会生成一个 my.keystore的文件。 /** * 对pdf进行签章 * @param src pdf文件输入流 * @param imgPath 签章图片路径 * @param reason 签章原因 * @param location 签章地点 * @return * @throws GeneralSecurityException * @throws IOException * @throws DocumentException */ public static byte[] sign(InputStream src,String imgPath,String reason,String location) throws GeneralSecurityException, IOException, DocumentException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] resBytes = null; try{ //读取keystore ,获得私钥和证书链 KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(ConvertImgToBase64Util.loadImgResource("templates/keystore/keystore.p12"),"123456".toCharArray()); String alias = (String)keyStore.aliases().nextElement(); PrivateKey PrivateKey = (PrivateKey) keyStore.getKey(alias, "123456".toCharArray()); Certificate[] chain = keyStore.getCertificateChain(alias); PdfReader pdfReader = new PdfReader(src); Rectangle rectangle= pdfReader.getPageSize(1); float urx = rectangle.getRight()-100; float ury = rectangle.getTop()-100; float llx = urx-200; float lly = ury-200; PdfStamper stamper = PdfStamper.createSignature(pdfReader, baos, '', null, false); // 获取数字签章属性对象,设定数字签章的属性 PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); appearance.setReason(reason); appearance.setLocation(location); appearance.setVisibleSignature(new Rectangle(llx,lly,urx,ury), 1, "sign"); //获取盖章图片 byte[] imgBytes = ConvertImgToBase64Util.image2Bytes(imgPath); Image image = Image.getInstance(imgBytes); appearance.setSignatureGraphic(image); //设置认证等级 appearance.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED); //印章的渲染方式,这里选择只显示印章 appearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC); ExternalDigest digest = new BouncyCastleDigest(); //签名算法,参数依次为:证书秘钥、摘要算法名称,例如MD5 | SHA-1 | SHA-2.... 以及 提供者 ExternalSignature signature = new PrivateKeySignature(PrivateKey, DigestAlgorithms.SHA1, null); //调用itext签名方法完成pdf签章 MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0,MakeSignature.CryptoStandard.CMS); resBytes = baos.toByteArray(); }catch (Exception e){ log.error("pdf文件签章异常:{}",e); }finally { try{ if(baos != null){ baos.close(); } }catch (IOException e){ log.error("关闭io流异常:{}",e); } } return resBytes; }上面代码出现的keystore.p12就是my.keystore 3 word转pdf 3.1 docx转pdf public static byte[] docxToPdf(InputStream src) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] resBytes = null; String result; try { // pdf文件的尺寸 Document pdfDocument = new Document(PageSize.A3, 72, 72, 72, 72); PdfWriter pdfWriter = PdfWriter.getInstance(pdfDocument, baos); XWPFDocument doc = new XWPFDocument(src); pdfWriter.setInitialLeading(20); java.util.List plist = doc.getParagraphs(); pdfWriter.open(); pdfDocument.open(); for (int i = 0; i < plist.size(); i++) { XWPFParagraph pa = plist.get(i); java.util.List runs = pa.getRuns(); for (int j = 0; j < runs.size(); j++) { XWPFRun run = runs.get(j); java.util.List piclist = run.getEmbeddedPictures(); Iterator iterator = piclist.iterator(); while (iterator.hasNext()) { XWPFPicture pic = iterator.next(); XWPFPictureData picdata = pic.getPictureData(); byte[] bytepic = picdata.getData(); Image imag = Image.getInstance(bytepic); pdfDocument.add(imag); } // 中文字体的解决 BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); Font font = new Font(bf, 11.0f, Font.NORMAL, BaseColor.BLACK); String text = run.getText(-1); byte[] bs; if (text != null) { bs = text.getBytes(); String str = new String(bs); Chunk chObj1 = new Chunk(str, font); pdfDocument.add(chObj1); } } pdfDocument.add(new Chunk(Chunk.NEWLINE)); } //需要关闭,不然无法获取到输出流 pdfDocument.close(); pdfWriter.close(); resBytes = baos.toByteArray(); } catch (Exception e) { log.error("docx转pdf文件异常:{}",e); }finally { try{ if(baos != null){ baos.close(); } }catch (IOException e){ log.error("docx转pdf关闭io流异常:{}",e); } } return resBytes; } 3.2 doc转pdf /** * doc转为pdf,先将doc转为html,再将html转为pdf,因为使用poi无法直接将doc转为pdf * @param src * @return */ public static byte[] doc2pdf(InputStream src){ byte[] res = null; try{ String html = OfficeToPdfUtil.doc2Html(src); html = OfficeToPdfUtil.formatHtml(html); res = OfficeToPdfUtil.htmlToPdf(html); }catch (Exception e){ log.error("doc转pdf异常:{}",e); } return res; } public class OfficeToPdfUtil { /** * html转为pdf * @param html * @return */ public static byte[] htmlToPdf(String html) { com.itextpdf.text.Document document = null; ByteArrayInputStream bais = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] resBytes = null; try { document = new com.itextpdf.text.Document(PageSize.A4); PdfWriter writer = PdfWriter.getInstance(document, baos); document.open(); bais = new ByteArrayInputStream(html.getBytes()); XMLWorkerHelper.getInstance().parseXHtml(writer, document, bais, Charset.forName("UTF-8"), new FontProvider() { @Override public boolean isRegistered(String s) { return false; } @Override public Font getFont(String s, String s1, boolean embedded, float size, int style, BaseColor baseColor) { // 配置字体 Font font = null; try { BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED); font = new Font(bf, size, style, baseColor); font.setColor(baseColor); } catch (Exception e) { e.printStackTrace(); } return font; } }); document.close(); writer.close(); resBytes = baos.toByteArray(); } catch (Exception e) { log.error("html转pdf异常:{}",e); } finally { if (document != null) { document.close(); } if (bais != null) { try { bais.close(); } catch (IOException e) { log.error("html转pdf关闭io流异常:{}",e); } } } return resBytes; } /** * doc文件转为html * @param inputStream * @return */ public static String doc2Html(InputStream inputStream) { String content = null; ByteArrayOutputStream baos = null; try { HWPFDocument wordDocument = new HWPFDocument(inputStream); WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument()); wordToHtmlConverter.setPicturesManager(new PicturesManager() { @Override public String savePicture(byte[] content, PictureType pictureType, String suggestedName, float widthInches, float heightInches) { return null; } }); wordToHtmlConverter.processDocument(wordDocument); org.w3c.dom.Document htmlDocument = wordToHtmlConverter.getDocument(); DOMSource domSource = new DOMSource(htmlDocument); baos = new ByteArrayOutputStream(); StreamResult streamResult = new StreamResult(baos); TransformerFactory tf = TransformerFactory.newInstance(); Transformer serializer = tf.newTransformer(); serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8"); serializer.setOutputProperty(OutputKeys.INDENT, "yes"); serializer.setOutputProperty(OutputKeys.METHOD, "html"); serializer.transform(domSource, streamResult); } catch (Exception e) { log.error("doc转html异常:{}",e); } finally { try { if (baos != null) { content = new String(baos.toByteArray(), "utf-8"); baos.close(); } } catch (Exception e) { log.error("doc转html关闭io流异常:{}",e); } } return content; } /** * 使用jsoup规范化html * @param html html内容 * @return 规范化后的html */ public static String formatHtml(String html) { org.jsoup.nodes.Document doc = Jsoup.parse(html); // 去除过大的宽度 String style = doc.attr("style"); if (StringUtils.isNotEmpty(style) && style.contains("width")) { doc.attr("style", ""); } Elements divs = doc.select("div"); for (org.jsoup.nodes.Element div : divs) { String divStyle = div.attr("style"); if (StringUtils.isNotEmpty(divStyle) && divStyle.contains("width")) { div.attr("style", ""); } } // jsoup生成闭合标签 doc.outputSettings().syntax(org.jsoup.nodes.Document.OutputSettings.Syntax.xml); doc.outputSettings().escapeMode(Entities.EscapeMode.xhtml); return doc.html(); } 4 ppt转pdf 4.1 pptx转pdf public static byte[] pptxToPdf(InputStream src) { Document document = null; XMLSlideShow slideShow = null; FileOutputStream fileOutputStream = null; PdfWriter pdfWriter = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] resBytes = null; try { //使用输入流pptx文件 slideShow = new XMLSlideShow(src); //获取幻灯片的尺寸 Dimension dimension = slideShow.getPageSize(); //创建一个写内容的容器 document = new Document(PageSize.A3, 72, 72, 72, 72); //使用输出流写入 pdfWriter = PdfWriter.getInstance(document, baos); //使用之前必须打开 document.open(); pdfWriter.open(); PdfPTable pdfPTable = new PdfPTable(1); //获取幻灯片 java.util.List slideList = slideShow.getSlides(); for (int i = 0, row = slideList.size(); i < row; i++) { //获取每一页幻灯片 XSLFSlide slide = slideList.get(i); for (XSLFShape shape : slide.getShapes()) { //判断是否是文本 if(shape instanceof XSLFTextShape){ // 设置字体, 解决中文乱码 XSLFTextShape textShape = (XSLFTextShape) shape; for (XSLFTextParagraph textParagraph : textShape.getTextParagraphs()) { for (XSLFTextRun textRun : textParagraph.getTextRuns()) { textRun.setFontFamily("宋体"); } } } } //根据幻灯片尺寸创建图形对象 BufferedImage bufferedImage = new BufferedImage((int)dimension.getWidth(), (int)dimension.getHeight(), BufferedImage.TYPE_INT_RGB); Graphics2D graphics2d = bufferedImage.createGraphics(); graphics2d.setPaint(Color.white); graphics2d.setFont(new java.awt.Font("宋体", java.awt.Font.PLAIN, 12)); //把内容写入图形对象 slide.draw(graphics2d); graphics2d.dispose(); //封装到Image对象中 Image image = Image.getInstance(bufferedImage, null); image.scalePercent(50f); // 写入单元格 pdfPTable.addCell(new PdfPCell(image, true)); document.add(image); } document.close(); pdfWriter.close(); resBytes = baos.toByteArray(); } catch (Exception e) { log.error("pptx转pdf异常:{}",e); } finally { try { if (baos != null) { baos.close(); } } catch (IOException e) { log.error("pptx转pdf关闭io流异常:{}",e); } } return resBytes; } 4.2 ppt转pdf /** * 将ppt转为pdf,兼容ppt和pptx * @param is * @return */ public static byte[] ppt2pdf(InputStream is) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] resBytes = null; try { Document pdfDocument = new Document(); PdfWriter pdfWriter = PdfWriter.getInstance(pdfDocument, baos); HSLFSlideShow hslfSlideShow = new HSLFSlideShow(is); double zoom = 2; if (hslfSlideShow == null) { XMLSlideShow ppt = new XMLSlideShow(is); if (ppt == null) { throw new NullPointerException("获取ppt文件数据失败"); } Dimension pgsize = ppt.getPageSize(); List slide = ppt.getSlides(); AffineTransform at = new AffineTransform(); at.setToScale(zoom, zoom); pdfDocument.setPageSize(new Rectangle((float) pgsize.getWidth(), (float) pgsize.getHeight())); pdfWriter.open(); pdfDocument.open(); PdfPTable table = new PdfPTable(1); for (XSLFSlide xslfSlide : slide) { BufferedImage img = new BufferedImage((int) Math.ceil(pgsize.width * zoom), (int) Math.ceil(pgsize.height * zoom), BufferedImage.TYPE_INT_RGB); Graphics2D graphics = img.createGraphics(); graphics.setTransform(at); graphics.setPaint(Color.white); graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height)); xslfSlide.draw(graphics); graphics.getPaint(); Image slideImage = Image.getInstance(img, null); table.addCell(new PdfPCell(slideImage, true)); } ppt.close(); pdfDocument.add(table); pdfDocument.close(); pdfWriter.close(); resBytes = baos.toByteArray(); return resBytes; } Dimension pgsize = hslfSlideShow.getPageSize(); List slides = hslfSlideShow.getSlides(); pdfDocument.setPageSize(new Rectangle((float) pgsize.getWidth(), (float) pgsize.getHeight())); pdfWriter.open(); pdfDocument.open(); AffineTransform at = new AffineTransform(); PdfPTable table = new PdfPTable(1); for (HSLFSlide hslfSlide : slides) { BufferedImage img = new BufferedImage((int) Math.ceil(pgsize.width * zoom), (int) Math.ceil(pgsize.height * zoom), BufferedImage.TYPE_INT_RGB); Graphics2D graphics = img.createGraphics(); graphics.setTransform(at); graphics.setPaint(Color.white); graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height)); hslfSlide.draw(graphics); graphics.getPaint(); Image slideImage = Image.getInstance(img, null); table.addCell(new PdfPCell(slideImage, true)); } hslfSlideShow.close(); pdfDocument.add(table); pdfDocument.close(); pdfWriter.close(); resBytes = baos.toByteArray(); return resBytes; } catch (Exception e) { log.error("ppt转为pdf异常:{}",e); } return resBytes; }这里兼容有点问题,当HSLFSlideShow hslfSlideShow = new HSLFSlideShow(is)无法创建对象时,io流无法再被使用了,则无法再去创建XMLSlideShow对象。但是可以使用此方法转ppt后缀的文件。 5 excel文件加图片水印,并加密 @Slf4j public class ExcelWaterMakerUtils { /** * 给Excel添加图片水印,并加密,返回新文件的byte数组 * @param imgPath * @param fileName * @param fis * @return */ public static byte[] addWaterMaker(String imgPath,String fileName, InputStream fis){ ByteArrayOutputStream baos = new ByteArrayOutputStream(); BufferedImage bufferImg = null; byte[] resBytes = null; try { Workbook workbook; if (fileName.endsWith(".xlsx")){ workbook = new XSSFWorkbook(fis); } else { workbook = new HSSFWorkbook(fis); } //设置Excel为只读 String password = RandomStringUtils.random(6,false,true); int sheetNumbers = workbook.getNumberOfSheets(); short rightNum = 3; short leftNum = 2; for (int i = 0; i < sheetNumbers; i++) { Sheet sheet = workbook.getSheetAt(i); sheet.protectSheet(password); Row row = sheet.getRow(1); if(row == null){ break; } short cellLastNum = row.getLastCellNum(); rightNum = (short) (cellLastNum-1); leftNum = (short) (cellLastNum - 2); ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); InputStream img = ConvertImgToBase64Util.loadImgResource(imgPath); bufferImg = ImageIO.read(img); //第二个参数将会决定插入图片形式,如果是一个png的图片,背景透明,但是此处设置为jpg格式将会自动添加黑色背景 ImageIO.write(bufferImg, "png", byteArrayOut); //画图的顶级管理器,一个sheet只能获取一个 Drawing drawing = sheet.createDrawingPatriarch(); //anchor主要用于设置图片的属性 ClientAnchor anchor = drawing.createAnchor(0, 0, 255, 255,leftNum, 1, rightNum, 1); // anchor.setAnchorType(2); //插入图片 drawing.createPicture(anchor, workbook.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG)); Picture pic = drawing.createPicture(anchor, workbook.addPicture(byteArrayOut.toByteArray(), Workbook.PICTURE_TYPE_PNG)); pic.resize(); } workbook.write(baos); resBytes = baos.toByteArray(); fis.close(); baos.close(); } catch (Exception e) { log.error("Excel盖章异常:{}",e); }finally{ try{ if(fis != null){ fis.close(); } if(baos != null){ baos.close(); } }catch (IOException ioe){ log.error("Excel盖章关闭io流异常:{}",ioe); } } return resBytes; } }图片的位置是根据excel表的行列来定位的,所以不同的excel文件图片的大小可能会有变化,需要优化下,我优化了很久没能实现,将就用着吧。。 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |