【问题标题】:Inserting attachment in PDF file using Java and iText使用 Java 和 iText 在 PDF 文件中插入附件
【发布时间】:2015-12-20 15:05:54
【问题描述】:

我已经能够编写代码来创建新的 PDF 或打开现有的 PDF 并追加。 我现在想要实现的是在其中插入另一个 PDF。以下是我迄今为止编写的附加 PDF 的示例代码。

Document document = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
PdfContentByte cb = writer.getDirectContent();


PdfReader reader = new PdfReader(templateInputStream);
PdfImportedPage page = writer.getImportedPage(reader, 1); 


document.newPage();
cb.addTemplate(page, 0, 0);

// Append sample line
document.add(new Paragraph("my timestamp")); 

document.close();

据我所知,Adobe 阅读器确实支持插入文档。不确定是否也可以使用 Java 代码来实现。

编辑:

以下是我编写的在 PDF 中嵌入 PDF 的代码。单击并打开嵌入的 pdf/附件时出现错误。

public class AddEmbeddedFile {
    public static final String SRC = "C:\\Users\\User\\Desktop\\testSource.pdf";
    public static final String Embed = "C:\\Users\\User\\Desktop\\testEmbed.pdf";
    public static final String DEST = "C:\\Users\\User\\Desktop\\testDest.pdf";
    public static void main(String[] args) throws IOException, DocumentException {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new AddEmbeddedFile().manipulatePdf(SRC, DEST, Embed);
    }
    public void manipulatePdf(String src, String dest, String embed) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(src);
        PdfReader reader2 = new PdfReader(embed);
        int n = reader2.getNumberOfPages();
        reader2.close();
        ByteArrayOutputStream boas;
        byte[] PDFContent = null;
        byte[] PDFContent2 = new byte[0];
        for (int i = 0; i < n; ) {
            reader2.selectPages(String.valueOf(++i));
            boas = new ByteArrayOutputStream();
            PdfStamper stamper2 = new PdfStamper(reader2, boas);
            PDFContent = boas.toByteArray();
            byte[] c = new byte[PDFContent.length + PDFContent2.length];
            System.arraycopy(PDFContent, 0, c, 0, PDFContent.length);
            System.arraycopy(PDFContent2, 0, c, PDFContent.length, PDFContent2.length);
            PDFContent2 = c;
        }
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(
                stamper.getWriter(), null, "tests.pdf", PDFContent2, "pdf", null, 0);
        stamper.addFileAttachment("some test file", fs);
        stamper.close();
    }
}

这是我收到的错误:

【问题讨论】:

  • @Stefan,你能确认一下它是否是开源的吗?此外,它只是插入文本和文本文档,而不是 pdf 文档。你能帮忙吗?谢谢。
  • iText 是在 AGPL 下发布的开源软件。这意味着您也必须将自己的代码发布为 AGPL。在许多情况下,这不包括在商业环境中使用 iText,除非您从 iText Software 购买商业许可。这在one-minute video 中有解释。简而言之:iText 是开源的,但这并不意味着您在商业应用程序中使用 iText 就不必购买商业许可证。
  • @BrunoLowagie,感谢您的解释。

标签: java pdf itext


【解决方案1】:

您在问题中使用的代码是错误的。如果您将PdfImportedPage 对象导入PdfWriter,您将失去原始文档中可能存在的所有交互性。您需要改用PdfStamper。

向现有 PDF 添加附件有两种不同的方法。其中一个已在 cmets 中提到,您参考 AddEmbeddedFile 示例:

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(
            stamper.getWriter(), null, "test.txt", "Some test".getBytes());
    stamper.addFileAttachment("some test file", fs);
    stamper.close();
}

您有一个现有的 PDF src,您在其中嵌入了一个文本文件。调整示例应该相当容易,以便添加 PDF 字节而不是纯文本。在这种情况下,最终用户只有在打开附件面板时才能看到 PDF。

另一种附加文件的方法是使用附件注释:

public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    PdfReader reader = new PdfReader(src);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(
        stamper.getWriter(), null, "test.txt", "Some test".getBytes());
    Rectangle rect = new Rectangle(36, 770, 72, 806);
    PdfAnnotation attachment = dfAnnotation.createFileAttachment(
        stamper.getWriter(), rect, "My attachment", fs);
    stamper.addAnnotation(attachment, 1);
    stamper.close();
}

这将在现有 PDF 的第一页上由rect 定义的坐标上添加可见注释。

您也可能错误地使用了“附加文件”的概念。也许您的意思是看到将一个文件连接到另一个文件。这在我对以下问题的回答中得到了解释:How to merge documents correctly?

更新:

您正在使用此方法创建PdfFileSpecification 实例:

fileEmbedded(
    PdfWriter writer,
    String filePath,
    String fileDisplay,
    byte[] fileStore,
    String mimeType,
    PdfDictionary fileParameter,
    int compressionLevel)

但是你的参数都错了:

PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(
    stamper.getWriter(), // correct
    null, // should be "C:\\Users\\User\\Desktop\\testEmbed.pdf"
    "tests.pdf", // correct
    PDFContent2, // this is completely wrong!!!
    "pdf", // should be "application/pdf"
    null, // OK
    0); // choosing 0 means that you don't want to compress the attachment. Why not?

你创建PdfContent2 的方式是完全错误的。很难想象你在这里想要达到什么目标。您以完全违反 PDF 参考的方式连接 PDF 字节。

【讨论】:

  • 非常感谢。我正在尝试在 PDF 中插入 PDF。我就是这样做的,我正在阅读我想插入的 PDF 的内容,然后在 CreateFileAttachement 中使用它。但我在打开附件时收到错误消息。我已经更新了我的问题(在 EDIT 部分下)以反映更新的代码和错误
【解决方案2】:

更新:

PdfFileSpecification fileSpecification = PdfFileSpecification.fileEmbedded(pdfWriter,
                    pdfAttach.getAbsolutePath(), pdfAttach.getName(), null);
pdfWriter.addFileAttachment("Sample Attachment", fileSpecification);

【讨论】:

  • 你想更新什么?为什么要更新它?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多