【问题标题】:Copy-pasting text from generated PDF using PDFBox results in garbage使用 PDFBox 从生成的 PDF 复制粘贴文本会导致垃圾
【发布时间】:2017-12-07 16:36:53
【问题描述】:

我有一些代码获取模板 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();
    }
}

【问题讨论】:

  • 请在您操作之前和之后分享一对示例 PDF。还请显示足够的代码以允许重现问题(即最好是sscce)。
  • 请说明您使用的 PDFBox 版本。
  • @Tilman 完成。作为旁注,我也尝试使用 2.0.8 版本,但它导致文本乱码,所以我恢复到我开始使用的版本。
  • 您的 contentStream 是如何创建的?如果您无法共享您的 PDF,请尝试使用公开的 PDF 进行复制。
  • @mkl 我添加了 SSCCE,唯一缺少的是字体。 Stackoverflow 没有上传功能,所以我不能把它放在任何地方。字体是相关的,如果我将其替换为内置字体之一,则不会出现问题。

标签: java pdf fonts copy-paste pdfbox


【解决方案1】:

这是一个已知问题 (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;
}

【讨论】:

  • 是的,这对我也有用。虽然我这样做了:document.save(new ByteArrayOutputStream()); 以防止写入实际文件。
  • 事实证明 PDDocument 不会挂起或以任何方式需要此 OutputStream。所以我使用了 NopOutputstream; private static class NopOutputStream extends OutputStream { public void write(int b) throws IOException {} public void write(byte b[]) throws IOException {} public void write(byte b[], int off, int len) throws IOException {} }
猜你喜欢
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多