【问题标题】:Copying PDF Attachments Including a .joboptions File in iText在 iText 中复制包含 .joboptions 文件的 PDF 附件
【发布时间】:2014-05-08 17:54:44
【问题描述】:

我正在尝试使用 iText 5.5 库来处理 PDF 中的信息。我想扫描 PDF 中的附件,如果它有附件,请制作它们的物理副本(不删除/编辑原始文件)。当附有 .joboptions 文件的 PDF 时,我遇到了问题。 我正在使用以下代码:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.pdf.PRStream;
import com.itextpdf.text.pdf.PdfArray;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfString;

public class extractAttachments{

public extractAttachments(String src, String dir) throws IOException {

    File folder = new File(dir);
       folder.mkdirs();
       PdfReader reader = new PdfReader(src);
       PdfDictionary root = reader.getCatalog();
       PdfDictionary names = root.getAsDict(PdfName.NAMES);
       PdfDictionary embedded = names.getAsDict(PdfName.EMBEDDEDFILES);
       PdfArray filespecs = embedded.getAsArray(PdfName.NAMES);
       for (int i = 0; i < filespecs.size(); ) {
         extractAttachment(reader, folder, filespecs.getAsString(i++),
         filespecs.getAsDict(i++));
       }
     }

    protected void extractAttachment(PdfReader reader, File dir, PdfString name, PdfDictionary filespec)
       throws IOException {
       PRStream stream;
       FileOutputStream fos;
       String filename;
       PdfDictionary refs = filespec.getAsDict(PdfName.EF);
       for (PdfName key : refs.getKeys()) {
         stream = (PRStream)PdfReader.getPdfObject(refs.getAsIndirectObject(key));
         filename = filespec.getAsString(key).toString();
         fos = new FileOutputStream(new File(dir, filename));
         fos.write(PdfReader.getStreamBytes(stream));
         fos.flush();
         fos.close();
       }
     }
  }

一旦到达PdfArray filespecs = embedded.getAsArray(PdfName.NAMES);,就会返回null。我不在乎是否复制了 .joboptions 文件,但是我确实希望复制其他附件(如果有的话)。有什么想法可以解决这个问题吗?

另外,如果您想使用上述 .joboptions 文件创建 PDF,请打开 PDF 文档,转到打印菜单并将打印机更改为“Adobe PDF”。现在选择属性,单击确定,然后在主打印菜单中单击打印。这将提示您选择保存文档的位置,并且新文档将有一个 .joboptions 作为附件。

【问题讨论】:

  • 您能否分享一个带有 .joboptions 文件的 pdf 文件,以便检查和重现问题?
  • @mkl 是的,这是一个带有附件的 pdf:app.box.com/s/j6jc6thn90pavbrriw05

标签: java itext


【解决方案1】:

您的代码不完整,因为它只理解非常原始的 EmbeddedFiles 结构。您的示例文件具有稍微复杂的 EmbeddedFiles 结构。你需要改进你的代码才能理解这些更复杂的结构。

详情

EmbeddedFiles 字典被指定为包含名称树:

EmbeddedFiles 名称树 (可选;PDF 1.4) 将名称字符串映射到文件的名称树 嵌入式文件流的规范(参见 7.11.4,“嵌入式 文件流”)。

ISO 32000-1 表 31 - 名称字典中的条目)

名称树应由节点构成,每个节点应为字典对象。表 36 显示了节点字典中的条目。节点应分为三种,具体取决于它们包含的特定条目。树应该总是有一个根节点,它应该包含一个条目:KidsNames,但不能同时包含两者。如果根节点有一个Names 条目,它应该是树中唯一的节点。如果它有一个 Kids 条目,则每个剩余​​节点都应该是一个中间节点,它应该包含一个 Limits 条目和一个 Kids 条目,或叶节点,应包含 Limits 条目和 Names 条目。

ISO 32000-1 第 7.9.6 节 - 名称树)

您的代码仅了解 根节点具有 Names 条目的种类,因此,是树中唯一的节点

...
PdfDictionary embedded = names.getAsDict(PdfName.EMBEDDEDFILES);
PdfArray filespecs = embedded.getAsArray(PdfName.NAMES);
...

另一方面,在您的示例 PDF 文件中,EmbeddedFiles 字典有一个 Kids 条目,因此您的代码无法理解:

【讨论】:

  • 你最后用什么来分解 PDF 信息?
  • 我使用基于 iText 构建的 RUPS。
猜你喜欢
  • 2015-12-20
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多