在iText中复制包含.joboptions文件的PDF附件

时间:2014-05-08 17:54:45

标签: java itext

我正在尝试使用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作为附件。

1 个答案:

答案 0 :(得分:0)

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

详情

指定 EmbeddedFiles 字典包含名称树:

  

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

     

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

     

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

     

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

您的代码只能理解根节点有名称条目的多样性,因此是树中唯一的节点

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

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

Sample PDF structure with EmbeddedFiles expanded