概要
记录一个批量PDF修改的功能,搜索一般是PDF遮罩层、不太符合所需要的业务逻辑,特此提供另一种思路、适用于PDF格式不复杂的。
注意pdf转换成html可能会丢失某些样式。
整体架构流程
1、把pdf通过Spire.PDF for Java 的 PDF 转为 HTML
2、读取HTML成字符串并内容替换及调整文字距离X轴、Y轴的距离
4、通过itextpdf 把html变成pdf或者通过浏览器打印变成pdf
技术细节
用到的jar包
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>html2pdf</artifactId>
<version>5.0.1</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc</artifactId>
<version>11.7.0</version>
</dependency>
测试代码
package com.ruoyi.project.demo.controller;
import cn.hutool.core.io.FileUtil;
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
import java.io.FileOutputStream;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.spire.pdf.FileFormat;
import com.spire.pdf.PdfDocument;
public class PdfUpdate {
public static void main(String[] args) throws Exception {
//创建PdfDocument的对象
PdfDocument pdf = new PdfDocument();
//加载PDF文件
pdf.loadFromFile("C:\\Users\\dell\\Desktop\\测试.pdf");
//将PDF文件保存为HTML文件
pdf.saveToFile("D:/PDFToHTML.html", FileFormat.HTML);
pdf.close();
String html = FileUtil.readUtf8String("D:/PDFToHTML.html");
//删除标记
html = html.replace("<text style=\"fill:#ff0000;font-family:Times New Roman;\" font-size=\"10\" xml:space=\"preserve\" x=\"20\" y=\"20\">Evaluation Warning : The document was created with Spire.PDF for java.</text>", "");
//删除字符
html = html.replace("<text style=\"fill:#000000;font-family:FF0;font-weight:bold;\" font-size=\"56\" x=\"241.426\" y=\"286.662\">检</text>", "");
html = html.replace("<text style=\"fill:#000000;font-family:FF0;font-weight:bold;\" font-size=\"56\" x=\"297.65\" y=\"286.662\">测</text>", "");
//调整位置
html = html.replace("<text style=\"fill:#000000;font-family:FF0;font-weight:bold;\" font-size=\"56\" x=\"185.202\" y=\"286.662\">",
"<text style=\"fill:#000000;font-family:FF0;font-weight:bold;\" font-size=\"56\" x=\"225.202\" y=\"286.662\">");
html = html.replace("<text style=\"fill:#000000;font-family:FF0;font-weight:bold;\" font-size=\"56\" x=\"353.874\" y=\"286.662\">",
"<text style=\"fill:#000000;font-family:FF0;font-weight:bold;\" font-size=\"56\" x=\"323.874\" y=\"286.662\">");
html = html.replace("<title>PDFToHTML</title>","<title></title>");
for (int i = 5; i < 100; i += 6) {
//删除
html = html.replace("<text style=\"fill:#000000;font-family:FF" + i + ";font-weight:bold;\" font-size=\"18\" x=\"279.028\" y=\"98.83795\">检</text>", "");
html = html.replace("<text style=\"fill:#000000;font-family:FF" + i + ";font-weight:bold;\" font-size=\"18\" x=\"297.1\" y=\"98.83795\">测</text>", "");
//后移
html = html.replace("<text style=\"fill:#000000;font-family:FF" + i + ";font-weight:bold;\" font-size=\"18\" x=\"242.884\" y=\"98.83795\">",
"<text style=\"fill:#000000;font-family:FF" + i + ";font-weight:bold;\" font-size=\"18\" x=\"257.17203\" y=\"98.83795\">");
html = html.replace("<text style=\"fill:#000000;font-family:FF" + i + ";font-weight:bold;\" font-size=\"18\" x=\"260.956\" y=\"98.83795\">",
"<text style=\"fill:#000000;font-family:FF" + i + ";font-weight:bold;\" font-size=\"18\" x=\"275.24402\" y=\"98.83795\">");
//前移
html = html.replace("<text style=\"fill:#000000;font-family:FF" + i + ";font-weight:bold;\" font-size=\"18\" x=\"315.17203\" y=\"98.83795\">",
"<text style=\"fill:#000000;font-family:FF" + i + ";font-weight:bold;\" font-size=\"18\" x=\"295.17203\" y=\"98.83795\">");
html = html.replace("<text style=\"fill:#000000;font-family:FF" + i + ";font-weight:bold;\" font-size=\"18\" x=\"333.24402\" y=\"98.83795\">",
"<text style=\"fill:#000000;font-family:FF" + i + ";font-weight:bold;\" font-size=\"18\" x=\"313.24402\" y=\"98.83795\">");
}
//如果用浏览器打印就生成新的html
FileUtil.writeString(html, "D:/newHtml.html","utf-8");
//直接生成pdf
createPdf(html);
}
/**
* 生成pdf并增加pdf编辑加密
* @param html
* @throws Exception
*/
public static void createPdf(String html) throws Exception{
String file = "D:/test.pdf";
// 创建一个输出流
FileOutputStream baos = new FileOutputStream(file);
ConverterProperties converterProperties = new ConverterProperties();
DefaultFontProvider fontProvider = new DefaultFontProvider(false,
false,false);
//增加中文字体、否则中文不显示
fontProvider.addFont("C:/Windows/Fonts/simsun.ttc,0");
converterProperties.setFontProvider(fontProvider);
HtmlConverter.convertToPdf(html, baos, converterProperties);
//加密处理
encryption(file);
}
/**
* 增加pdf编辑加密
* @param filePath
* @throws Exception
*/
public static void encryption(String filePath) throws Exception{
// 加密后的PDF 文件路径
String destPdf = "D:/dest.pdf";
// 加密密钥
String password = "123456";
// 创建 PDF 读取器
PdfReader reader = new PdfReader(filePath);
// 创建 PDF 写入器
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(destPdf));
// 处理 PDF 文档的权限、参数1打开加密、参数2编辑加密
stamper.setEncryption(null, password.getBytes(), PdfWriter.ALLOW_PRINTING | PdfWriter.ALLOW_COPY, PdfWriter.ENCRYPTION_AES_128);
// 关闭 PDF 文档
stamper.close();
reader.close();
}
}
效果图
处理前:
处理后:
html中的文本格式