IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    使用Aspose.Words将word转PDF并添加公章

    满心记发表于 2024-07-18 01:23:27
    love 0

    很久没写技术文章了,前段时间在研究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包

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    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;

    }
    }

    写在最后

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



沪ICP备19023445号-2号
友情链接