满心记 我在人间混日子

使用Aspose.Words将word转PDF

很久没写技术文章了,前段时间在研究word转pdf,以及加盖印章这部分,已经实现了,当然网络上也有很多文章,但是有的要么依赖导入不成功,要么逻辑有问题,总的来说,可能还是文章太老了,有些东西都不适用了,我这里正好也分享一下,希望能帮得上大家。

代码可直接测试运行,我这里JDK17,Maven3.5,IDEA2023

业务需求

我们现有业务是通过poi来实现内容转word,以及各类电子签名和图片,平时相关人员是将word下载下来,然后盖章扫描,再传回平台。
现在需求是在特殊情况下,需要特殊处理,不走这个流程了,因为太麻烦,所以想再平台上直接生成盖章后的pdf,直接使用。

其实需求很简单,就是要最终盖好章的pdf,发给客户,好,那我们就开始吧。

选用技术

我大概了解了下,常用的主要就是下面几种方式

  • 使用Aspose.Words库:Aspose.Words是一个功能强大的库,支持将Word文档转换为PDF格式。你需要将Aspose.Words的许可证字符串设置到你的程序中,然后使用相应的API进行转换。
  • 使用documents4j库:对于Windows环境,documents4j库可以在有Microsoft Office服务的情况下将Word文档转换为PDF。这需要安装Microsoft Office,并且可能需要在程序中配置Office的路径。
  • 使用LibreOffice服务:在Linux环境下,可以利用LibreOffice服务将Word文档转换为PDF。这需要在服务器上安装LibreOffice,并且可能需要在程序中配置LibreOffice的路径。
  • 使用Apache POI和iText库:这种方法适用于处理.doc和.docx格式的Word文档。首先使用Apache POI读取Word文档的内容,然后使用iText库将内容转换为PDF格式。这种方法可能需要处理Word文档中的复杂格式和布局。
    使用其他第三方库:例如Spire.Doc库,它提供了一个简单的API来将Word文档转换为PDF格式。你可以通过下载jar包或使用Maven仓库安装导入这个库。
  • 使用OpenOffice服务:如果你的环境中安装了OpenOffice,你可以使用Java调用OpenOffice的服务来将Word文档转换为PDF。这需要在Java程序中配置OpenOffice的路径和服务设置。

权衡之下,我选择了Aspose.Words,其实选择OpenOffice效果最好,以后等我有空了,会选择这种方式实现,到时候再分享。

实现逻辑

导入依赖,由于Aspose.Words在私服仓库,所以直接pom是无法导入的,需要将jar包手动传到maven仓库,然后在pom引入

去官网下载jar包记得选择21.6的jar包

<dependency>
  <groupId>com.aspose</groupId>
  <artifactId>aspose-words</artifactId>
  <version>21.6</version>
  <classifier>jdk17</classifier>
</dependency>
<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>itext-asian</artifactId>
  <version>5.2.0</version>
</dependency>
<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>itextpdf</artifactId>
  <version>5.5.13</version>
</dependency>
<dependency>
  <groupId>com.itextpdf.tool</groupId>
  <artifactId>xmlworker</artifactId>
  <version>5.5.13</version>
</dependency>

建议使用21.6版本,这个版本我去了水印(正版需要购买证书),相当于破解了吧,其它版本暂未尝试。

其实就是两个文件,WordPdfUtil.java和ImageUtil

WordPdfUtil.java

package com.manxin.ltd.datacenter.util;

import com.aspose.words.Document;
import com.aspose.words.SaveFormat;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.lang.reflect.Modifier;

public class WordToPdfUtils {

   public static void main(String[] args)throws Exception {
       Document doc = null;

       //去水印
       Class<?> aClass = Class.forName("com.aspose.words.zzXyu");
       java.lang.reflect.Field zzZXG = aClass.getDeclaredField("zzZXG");
       zzZXG.setAccessible(true);
       java.lang.reflect.Field modifiersField = zzZXG.getClass().getDeclaredField("modifiers");
       modifiersField.setAccessible(true);
       modifiersField.setInt(zzZXG, zzZXG.getModifiers() & ~Modifier.FINAL);
       zzZXG.set(null, new byte[]{76, 73, 67, 69, 78, 83, 69, 68});

       try {
           String resultPath = "E:\\download\\test\\test" + ".pdf";
           FileOutputStream os = new FileOutputStream(resultPath);
           doc = new Document(new FileInputStream("E:\\download\\test\\test.docx"));
           doc.save(os, SaveFormat.PDF);

           //添加印章
           FileInputStream pdfIs = new FileInputStream("E:\\download\\test\\test.pdf");
           // 1.1 读取模板文件
           PdfReader reader = new PdfReader(pdfIs);
           // 1.2 创建文件输出流
           FileOutputStream out = new FileOutputStream("E:\\download\\test\\testnew.pdf");
           // 2、创建PdfStamper对象
           PdfStamper stamper = new PdfStamper(reader, out);
           // 4、读取公章
           String path = "E:\\download\\test\\baogao.png";
           BufferedImage bufferedImage = ImageIO.read(new FileInputStream(path));
           BufferedImage[] imgs = ImageUtil.splitImage(bufferedImage, 1, 2);
           // 5、读公章图片
           Image image = Image.getInstance(ImageUtil.imageToBytes(bufferedImage));
           // 公章大小,x轴
           int chunkWidth = 150;
           // 公章大小,y轴
           int chunkHeight = 150;
           // pdf页面页码
           int pdfPages = reader.getNumberOfPages();

           // 6.3 最后一页盖公章
           image.scaleToFit(chunkWidth, chunkHeight);
           //得到的位置有些许偏差,自行调节
           image.setAbsolutePosition(380, 310);
           stamper.getOverContent(pdfPages).addImage(image);
           stamper.close();
           out.close();
           reader.close();
           pdfIs.close();
       } catch (Exception e) {
           e.printStackTrace();
       }
   }
}

ImageUtil.java

package com.whohs.smartmsp.opscenter.util;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class ImageUtil {

   /**
    * @Description:分割图片
    * @Date: 2021/12/9  8:34
    * @Param image: 图片BufferedImage流
    * @Param rows: 分割行
    * @Param cols: 分割列
    * @return: java.awt.image.BufferedImage[]  返回分割后的图片流
    **/
   public static BufferedImage[] splitImage(BufferedImage image, int rows, int cols) {
       // 分割成4*4(16)个小图
       int chunks = rows * cols;
       // 计算每个小图的宽度和高度
       int chunkWidth = image.getWidth() / cols + 3;// 向右移动3
       int 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.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;
   }


   /**
    * @Description:  将BufferedImage转换成字节数组
    * @Date: 2021/12/6  17:31
    * @Param bufferedImage:
    * @return: byte[]
    **/
   public static   byte[] imageToBytes(BufferedImage bufferedImage) throws IOException {

       ByteArrayOutputStream baos = new ByteArrayOutputStream();
       ImageIO.write( bufferedImage, "png", baos );
       baos.flush();
       byte[] imageInByte = baos.toByteArray();
       baos.close();

       return imageInByte;

   }
}

写在最后

代码就不解释了,几乎都有注释,大家一看就清楚了,有此类需求的可以做为参考。

发表评论

提交评论