使用 PDFBox 从生成的 PDF 复制粘贴文本导致垃圾
Copy-pasting text from generated PDF using PDFBox results in garbage
我有一些代码采用模板 PDF、创建新 PDF、将新 PDF 覆盖在模板 PDF 上并将结果写入流。所有这些都使用 PDFBox 2.0.4.
问题是将生成的 PDF 中的文本复制粘贴到文本编辑器会导致出现垃圾文本。
这只发生在我的代码添加的文本上,原始模板中的文本仍然可以正常工作。我添加的文本是使用自定义字体添加的。
如何修复生成的 PDF 以便可以复制粘贴文本?
SSCCE:
public class PDFTest {
private static final String FONT = "/fonts/font.ttf";
public static void main(final String... args) throws IOException, FontFormatException {
final Overlay overlay = new Overlay();
overlay.setInputPDF(newDocument("Input text", 400));
overlay.setAllPagesOverlayPDF(newDocument("Test text", 200));
try (final PDDocument document = overlay.overlay(new HashMap<>())) {
document.save("example.pdf");
}
}
private static PDDocument newDocument(final String text, final int offsetY) throws IOException, FontFormatException {
final PDDocument document = new PDDocument();
document.addPage(insertTextInPage(document, text, offsetY));
return document;
}
private static PDPage insertTextInPage(final PDDocument document, final String text, final int offsetY) throws IOException, FontFormatException {
try (final InputStream fontStream = PDFTest.class.getResourceAsStream(FONT)) {
final PDFont normalFont = PDType0Font.load(document, fontStream);
final PDPage page = new PDPage();
try (final PDPageContentStream contentStream = new PDPageContentStream(document, page, APPEND, false)) {
addTextBlock(contentStream, normalFont, text, offsetY);
}
return page;
}
}
private static void addTextBlock(final PDPageContentStream contentStream, final PDFont font, final String text, final int offsetY)
throws IOException {
contentStream.beginText();
contentStream.setFont(font, 16);
contentStream.newLineAtOffset(20, offsetY);
contentStream.showText(text);
contentStream.endText();
}
}
这是一个已知问题 (PDFBOX-3243),使用子集字体构建的文件(您使用的是非常高效的 PDType0Font.load()
)在保存之前处于中间状态,这是子集化发生的时间。
适合您的解决方案:要么保存并重新加载,要么保存为虚拟文件。在 Windows 中,我像这样更改了 newDocument
,它起作用了:
private static PDDocument newDocument(final String text, final int offsetY) throws IOException, FontFormatException
{
final PDDocument document = new PDDocument();
document.addPage(insertTextInPage(document, text, offsetY));
document.save("nul"); // NEW!
return document;
}
我有一些代码采用模板 PDF、创建新 PDF、将新 PDF 覆盖在模板 PDF 上并将结果写入流。所有这些都使用 PDFBox 2.0.4.
问题是将生成的 PDF 中的文本复制粘贴到文本编辑器会导致出现垃圾文本。
这只发生在我的代码添加的文本上,原始模板中的文本仍然可以正常工作。我添加的文本是使用自定义字体添加的。
如何修复生成的 PDF 以便可以复制粘贴文本?
SSCCE:
public class PDFTest {
private static final String FONT = "/fonts/font.ttf";
public static void main(final String... args) throws IOException, FontFormatException {
final Overlay overlay = new Overlay();
overlay.setInputPDF(newDocument("Input text", 400));
overlay.setAllPagesOverlayPDF(newDocument("Test text", 200));
try (final PDDocument document = overlay.overlay(new HashMap<>())) {
document.save("example.pdf");
}
}
private static PDDocument newDocument(final String text, final int offsetY) throws IOException, FontFormatException {
final PDDocument document = new PDDocument();
document.addPage(insertTextInPage(document, text, offsetY));
return document;
}
private static PDPage insertTextInPage(final PDDocument document, final String text, final int offsetY) throws IOException, FontFormatException {
try (final InputStream fontStream = PDFTest.class.getResourceAsStream(FONT)) {
final PDFont normalFont = PDType0Font.load(document, fontStream);
final PDPage page = new PDPage();
try (final PDPageContentStream contentStream = new PDPageContentStream(document, page, APPEND, false)) {
addTextBlock(contentStream, normalFont, text, offsetY);
}
return page;
}
}
private static void addTextBlock(final PDPageContentStream contentStream, final PDFont font, final String text, final int offsetY)
throws IOException {
contentStream.beginText();
contentStream.setFont(font, 16);
contentStream.newLineAtOffset(20, offsetY);
contentStream.showText(text);
contentStream.endText();
}
}
这是一个已知问题 (PDFBOX-3243),使用子集字体构建的文件(您使用的是非常高效的 PDType0Font.load()
)在保存之前处于中间状态,这是子集化发生的时间。
适合您的解决方案:要么保存并重新加载,要么保存为虚拟文件。在 Windows 中,我像这样更改了 newDocument
,它起作用了:
private static PDDocument newDocument(final String text, final int offsetY) throws IOException, FontFormatException
{
final PDDocument document = new PDDocument();
document.addPage(insertTextInPage(document, text, offsetY));
document.save("nul"); // NEW!
return document;
}