如何用 ITextPDF 库替换 pdf 文件中的文本?
How to replace a text in pdf file with ITextPDF library?
我需要用实际值替换像 ${placeholder} 这样的占位符,但我找不到任何可行的解决方案...我一直在关注 https://itextpdf.com/en/resources/examples/itext-7/replacing-pdf-objects 但它没有工作。有人知道怎么做吗?
一般来说,"replace" pdf 文件的内容并不是那么容易,因为它可以用不同的方式编写。例如,假设您要将块 "Hello" 替换为块 "World"。如果 "Hello" 已作为一个完整的单词写入 pdf,那么你会很幸运。它可能被写成 "He" 和 "llo",甚至 "o","l","l","e","H",这些字母可能会放在内容流的不同部分。
但是可以删除内容,然后将一些其他内容放在同一位置。
让我们看看如何实现。
1) 我建议你使用 iText 的 pdfSweep
,因为这个工具能够检测放置内容的区域并删除内容(重要的是要提到 pdfSweep 不会隐藏内容,它将完全删除)
让我们讨论一下 redactTonySoprano
测试。如您所见,可以提供一些正则表达式(例如,“"Tony( |_)Soprano"、"Soprano" 和 "Sopranoes"),iText 将编辑所有匹配的内容。
然后您可以使用 iText 通过低级 api (PdfCanvas) 或更复杂的高级 api (Canvas) 在这些区域上写一些文本等)。
让我们稍微修改一下我之前提到的女高音样本:
2) 让我们在编辑区域添加一些文本:
for (IPdfTextLocation location : strategy.getResultantLocations()) {
PdfPage page = pdf.getPage(location.getPageNumber()+1);
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), page.getDocument());
Canvas canvas = new Canvas(pdfCanvas, pdf, location.getRectangle());
canvas.add(new Paragraph("SECURED").setFontSize(8));
}
结果并不理想,但这只是概念验证。可以覆盖提取策略并定义编辑内容的字体,以便它可以用于要放置在编辑区域的新文本。
下面使用 iText 替换 PDF 内容的示例代码
File dir = new File("./");
File [] files = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".pdf");
}
});
for (File pdffile : files) {
System.out.println(pdffile.getName());
PdfReader reader = null;
reader = new PdfReader(pdffile.toString());
PdfDictionary dict = reader.getPageN(1);
PdfObject object = dict.getDirectObject(PdfName.CONTENTS);
if (object instanceof PRStream) {
PRStream stream = (PRStream)object;
byte[] data = PdfReader.getStreamBytes(stream);
String dd = new String(data);
dd = dd.replace("0 0 0 rg\n()Tj", "0 0 0 rg\n(Plan Advanced Payment)Tj");
System.out.print(dd);
stream.setData(dd.getBytes());
}
PdfStamper stamper = new PdfStamper(reader,
new FileOutputStream("./output/"+pdffile.getName())); // output PDF
stamper.close();
reader.close();
}
我需要用实际值替换像 ${placeholder} 这样的占位符,但我找不到任何可行的解决方案...我一直在关注 https://itextpdf.com/en/resources/examples/itext-7/replacing-pdf-objects 但它没有工作。有人知道怎么做吗?
一般来说,"replace" pdf 文件的内容并不是那么容易,因为它可以用不同的方式编写。例如,假设您要将块 "Hello" 替换为块 "World"。如果 "Hello" 已作为一个完整的单词写入 pdf,那么你会很幸运。它可能被写成 "He" 和 "llo",甚至 "o","l","l","e","H",这些字母可能会放在内容流的不同部分。
但是可以删除内容,然后将一些其他内容放在同一位置。
让我们看看如何实现。
1) 我建议你使用 iText 的 pdfSweep
,因为这个工具能够检测放置内容的区域并删除内容(重要的是要提到 pdfSweep 不会隐藏内容,它将完全删除)
让我们讨论一下 redactTonySoprano
测试。如您所见,可以提供一些正则表达式(例如,“"Tony( |_)Soprano"、"Soprano" 和 "Sopranoes"),iText 将编辑所有匹配的内容。
然后您可以使用 iText 通过低级 api (PdfCanvas) 或更复杂的高级 api (Canvas) 在这些区域上写一些文本等)。
让我们稍微修改一下我之前提到的女高音样本:
2) 让我们在编辑区域添加一些文本:
for (IPdfTextLocation location : strategy.getResultantLocations()) {
PdfPage page = pdf.getPage(location.getPageNumber()+1);
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), page.getDocument());
Canvas canvas = new Canvas(pdfCanvas, pdf, location.getRectangle());
canvas.add(new Paragraph("SECURED").setFontSize(8));
}
结果并不理想,但这只是概念验证。可以覆盖提取策略并定义编辑内容的字体,以便它可以用于要放置在编辑区域的新文本。
下面使用 iText 替换 PDF 内容的示例代码
File dir = new File("./");
File [] files = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".pdf");
}
});
for (File pdffile : files) {
System.out.println(pdffile.getName());
PdfReader reader = null;
reader = new PdfReader(pdffile.toString());
PdfDictionary dict = reader.getPageN(1);
PdfObject object = dict.getDirectObject(PdfName.CONTENTS);
if (object instanceof PRStream) {
PRStream stream = (PRStream)object;
byte[] data = PdfReader.getStreamBytes(stream);
String dd = new String(data);
dd = dd.replace("0 0 0 rg\n()Tj", "0 0 0 rg\n(Plan Advanced Payment)Tj");
System.out.print(dd);
stream.setData(dd.getBytes());
}
PdfStamper stamper = new PdfStamper(reader,
new FileOutputStream("./output/"+pdffile.getName())); // output PDF
stamper.close();
reader.close();
}