web中的jacob运用(包括使用itext为word加水印)
使用jacob的demo我在上一篇文章中已经做了笔记,接下来在这里我要记录jacob在web应用中的使用,同时也使用了itext为pdf添加水水印,框架为了方便使用的ssm框架。
搭建ssm框架这里就不做详细的介绍了,在我的博客中有这篇文章,详见http://www.cnblogs.com/advanceBlog/p/7858584.html
首先编写工具类word2PdfUtil.java,其中包括了word转pdf方法和itext加水印方法,代码如下:
package com.advance.util; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.net.MalformedURLException; import com.jacob.activeX.ActiveXComponent; import com.jacob.com.ComThread; import com.jacob.com.Dispatch; import com.lowagie.text.BadElementException; import com.lowagie.text.DocumentException; import com.lowagie.text.Image; import com.lowagie.text.Rectangle; import com.lowagie.text.pdf.BaseFont; import com.lowagie.text.pdf.PdfContentByte; import com.lowagie.text.pdf.PdfGState; import com.lowagie.text.pdf.PdfReader; import com.lowagie.text.pdf.PdfStamper; public class Word2PdfUtil { static final int wdFormatPDF = 17;// word转PDF 格式 private final static float imageFillOpacity = 0.3f;//图片水印透明度 private final static float imageScalePercent = 70;//水印图片缩放百分比 private final static float imagePositionX = 80;//水印图片距离本页最左方的数据 private final static float imagePositionY = 130;//水印图片距离本页最下方的数据 public static void word2pdf(String source, String target) { //初始化进程 ComThread.InitMTA(true); ActiveXComponent app = null; Dispatch docs = null; Dispatch doc = null; try { app = new ActiveXComponent("Word.Application"); app.setProperty("Visible", false); docs = app.getProperty("Documents").toDispatch(); doc = Dispatch.call(docs, "Open", source, false, true).toDispatch(); File tofile = new File(target); deleteFile(tofile.getName()); Dispatch.call(doc, "SaveAs", target, wdFormatPDF); Dispatch.call(doc, "Close", false); } catch (Exception e) { e.printStackTrace(); } finally { //释放资源 if(doc != null){ doc.safeRelease(); } if(docs != null){ docs.safeRelease(); } if (app != null) { app.invoke("Quit", 0); app.safeRelease(); } //关闭进程 ComThread.Release(); } } public static int addWaterMarker(String inputPdfPath,String code,String imagePath,String outPdfPath) throws Exception, IOException{ // 待加水印的文件 PdfReader reader = null; Rectangle pageSize = null; try { reader = new PdfReader( inputPdfPath); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 加完水印的文件 PdfStamper stamper = null; try { stamper = new PdfStamper(reader, new FileOutputStream( outPdfPath)); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } int total = reader.getNumberOfPages() + 1; PdfContentByte content = null; PdfContentByte under = null; BaseFont font = BaseFont.createFont("C://WINDOWS/Fonts/SIMSUN.TTC,1", "Identity-H",true); char c = 0; int rise = 0; int j = code.length(); Image image = null; try { image = Image.getInstance(imagePath); } catch (BadElementException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 循环对每页插入水印 for (int i = 1; i < total; i++) { //添加文字水印 rise = 400; under = stamper.getUnderContent(i); pageSize = reader.getPageSize(i); float marginTop = pageSize.getHeight()/2-20; float marginLeft = pageSize.getWidth()-code.length()*14; float imagePositionX = pageSize.getWidth()/2 - image.getWidth()/2; float imagePositionY = pageSize.getHeight()/2 - image.getHeight()/2; image.setAbsolutePosition(imagePositionX, imagePositionY); image.scalePercent(imageScalePercent); under.beginText(); //设置合同编号水印字体字号 under.setFontAndSize(font,14); //合同编号水印位置调整,参考图片水印位置 under.setTextMatrix(marginLeft, marginTop); for(int k = 0;k < j;k++){ under.setTextRise(rise); c=code.charAt(k); under.showText(c+""); } under.endText(); // 圖片水印的起始 content = stamper.getOverContent(i); //设置透明度 PdfGState gs = new PdfGState(); gs.setFillOpacity(imageFillOpacity); content.setGState(gs); try { content.addImage(image); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } content.endText(); } try { stamper.close(); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } deleteFile(inputPdfPath); return total; } public static void deleteFile(String fileName) throws Exception{ File file = new File(fileName); if (file.exists() && file.isFile()) { file.delete(); } } }
然后编写controller方法IndexController.java,其中包含了上传以及下载方法(我为了偷懒,将创建文件夹的方法在controller中创建了,这个不符合规范),代码如下:
package com.advance.controller; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.UUID; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import com.advance.util.Word2PdfUtil; @Controller public class IndexController { private final static String savePDFPath = "C://upload/PDF"; private final static String tempPath = "C://upload/TEMP"; private final static String imgPath = "C://upload/PDF/IMG"; static{ File savePDFDir = new File(savePDFPath); File tempDir = new File(tempPath); File imgDir = new File(imgPath); if(!savePDFDir.exists()){ savePDFDir.mkdirs(); } if(!tempDir.exists()){ tempDir.mkdirs(); } if(!imgDir.exists()){ imgDir.mkdirs(); } } @RequestMapping("/index.html") public String index(HttpServletRequest request){ return "index"; } @RequestMapping("/Word2PdfPage.html") public String toPage(HttpServletRequest request,String PDFName){ if(PDFName != "" && PDFName != null){ request.setAttribute("PDFName", PDFName); } return "word2Pdf"; } /** * 仅仅是word转pdf * @param file * @return * @throws Exception */ @RequestMapping("/convertPdf.html") public String doConvert(@RequestParam("file")MultipartFile file,HttpServletRequest request) throws Exception{ String oriName = file.getOriginalFilename(); String toPath = tempPath+"/"+oriName; file.transferTo(new File(toPath)); String PDFName = UUID.randomUUID().toString()+".pdf"; String PDFPath = savePDFPath+"/"+PDFName; Word2PdfUtil.word2pdf(toPath, PDFPath); // Word2PdfUtil.addWaterMarker(PDFTempFilePath, "哈哈哈", "C://Users/advance/Desktop/a.jpg", savePath+"/"+UUID.randomUUID().toString()+".pdf"); Word2PdfUtil.deleteFile(toPath); // Word2PdfUtil.deleteFile(PDFTempFilePath); return "redirect:Word2PdfPage.html?PDFName="+PDFName; } @RequestMapping("/Word2PdfAddWaterMakerPage.html") public String Word2PdfAddWaterMakerPage(HttpServletRequest request,String PDFName){ if(PDFName != "" && PDFName != null){ request.setAttribute("PDFName", PDFName); } return "word2PdfAddMarker"; } @RequestMapping("/convertPdfAddWaterMarker.html") public String convertPdfAddWaterMarker(@RequestParam("file")MultipartFile file,@RequestParam("img")MultipartFile img,HttpServletRequest request) throws Exception{ String code = request.getParameter("code"); //上传图片 String imgOriName = img.getOriginalFilename(); String toImgPath = imgPath+"/"+imgOriName; img.transferTo(new File(toImgPath)); //上传文件 String oriName = file.getOriginalFilename(); String toPath = tempPath+"/"+oriName; file.transferTo(new File(toPath)); String PDFTempName = UUID.randomUUID().toString()+".pdf"; String PDFTempPath = savePDFPath+"/"+PDFTempName; Word2PdfUtil.word2pdf(toPath, PDFTempPath); String PDFName = UUID.randomUUID().toString()+".pdf"; Word2PdfUtil.addWaterMarker(PDFTempPath, code, toImgPath, savePDFPath+"/"+PDFName); Word2PdfUtil.deleteFile(toImgPath); Word2PdfUtil.deleteFile(toPath); Word2PdfUtil.deleteFile(PDFTempPath); return "redirect:Word2PdfAddWaterMakerPage.html?PDFName="+PDFName; } @RequestMapping("/download.html") public ResponseEntity<byte[]> download(String name) throws IOException{ byte[] file = null; InputStream in = new FileInputStream(savePDFPath+"/"+name); try { file = new byte[in.available()]; } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } try { in.read(file); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } HttpHeaders headers = new HttpHeaders(); try { headers.add("Content-Disposition", "attachment;filename="+new String(name.getBytes("gbk"),"iso-8859-1")); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } in.close(); HttpStatus statusCode = HttpStatus.OK; ResponseEntity<byte[]> response = new ResponseEntity<>(file,headers, statusCode); return response; } }
这其中也碰到了很多问题:
1,如果你装的是wps的话,如果报错信息为 Can't get object clsid from progid的话,这个时候需要将wps卸载换成word;
2.若报错信息为Invoke of: SaveAs
Source: Microsoft Word
Description: 命令失败
的话,那么你还需要安装一个插件SaveAsPDFandXPS.exe,office的官网有提供,地址为https://www.microsoft.com/zh-cn/download/details.aspx?id=7
3.还有一个很奇怪的错误,com.jacob.com.ComFailException: VariantChangeType failed ,如果出现这个错误的话,那就是需要在你的C:\Windows\System32\config\systemprofile与C:\Windows\SysWOW64\config\systemprofile与下创建文件夹Desktop
4.在使用时,一定要记得关闭你的进程以及释放资源,要不然很严重的,有可能会导致错误:jacob Can't co-create object
当然如果报错信息为缺少dll文件的话那就是你没有将dll文件正确的放入到你使用jdk的jre的bin目录下。这个错误信息有很多,需要慢慢调试,千万不能心浮气躁。