很久没写技术文章了,前段时间在研究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"); PdfReader reader = new PdfReader(pdfIs); FileOutputStream out = new FileOutputStream("E:\\download\\test\\testnew.pdf"); PdfStamper stamper = new PdfStamper(reader, out); String path = "E:\\download\\test\\baogao.png"; BufferedImage bufferedImage = ImageIO.read(new FileInputStream(path)); BufferedImage[] imgs = ImageUtil.splitImage(bufferedImage, 1, 2); Image image = Image.getInstance(ImageUtil.imageToBytes(bufferedImage)); int chunkWidth = 150; int chunkHeight = 150; int pdfPages = reader.getNumberOfPages();
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 {
public static BufferedImage[] splitImage(BufferedImage image, int rows, int cols) { int chunks = rows * cols; int chunkWidth = image.getWidth() / cols + 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; }
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;
} }
|
写在最后
代码就不解释了,几乎都有注释,大家一看就清楚了,有此类需求的可以做为参考。