1

既存の PDF/A-3 にファイルを添付しようとしています。

このでは、PDF/A-3 を作成してコンテンツを添付する方法について説明します。

私の次のステップは、コードを変更し、ドキュメントの代わりに PdfAStamper を使用することでした。

これが私の結果のコードです。

private ByteArrayOutputStream append(byte[] content, InputStream inPdf) throws IOException, DocumentException {

  ByteArrayOutputStream result = new ByteArrayOutputStream(16000);
  PdfReader reader = new PdfReader(inPdf);
  PdfAStamper stamper = new PdfAStamper(reader, result, PdfAConformanceLevel.PDF_A_3B);

  stamper.createXmpMetadata();

  // Creating PDF/A-3 compliant attachment.
  PdfDictionary embeddedFileParams = new PdfDictionary();
  embeddedFileParams.put(PARAMS, new PdfName(ZF_NAME));
  embeddedFileParams.put(MODDATE, new PdfDate());
  PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(stamper.getWriter(), null,ZF_NAME, content , "text/xml", embeddedFileParams,0);
  fs.put(AFRELATIONSHIP, Alternative);
  stamper.addFileAttachment("file description",fs);

  stamper.close();
  reader.close();
  return result;
}

エラーのスタックトレースは次のとおりです。

    com.itextpdf.text.pdf.PdfAConformanceException: EF key of the file specification dictionary for an embedded file shall contain dictionary with valid F key.
    at com.itextpdf.text.pdf.internal.PdfA3Checker.checkFileSpec(PdfA3Checker.java:95)
    at com.itextpdf.text.pdf.internal.PdfAChecker.checkPdfAConformance(PdfAChecker.java:198)
    at com.itextpdf.text.pdf.internal.PdfAConformanceImp.checkPdfIsoConformance(PdfAConformanceImp.java:70)
    at com.itextpdf.text.pdf.PdfWriter.checkPdfIsoConformance(PdfWriter.java:3380)
    at com.itextpdf.text.pdf.PdfWriter.checkPdfIsoConformance(PdfWriter.java:3376)
    at com.itextpdf.text.pdf.PdfFileSpecification.toPdf(PdfFileSpecification.java:309)
    at com.itextpdf.text.pdf.PdfIndirectObject.writeTo(PdfIndirectObject.java:157)
    at com.itextpdf.text.pdf.PdfWriter$PdfBody.write(PdfWriter.java:424)
    at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:402)
    at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:381)
    at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:334)
    at com.itextpdf.text.pdf.PdfWriter.addToBody(PdfWriter.java:819)
    at com.itextpdf.text.pdf.PdfFileSpecification.getReference(PdfFileSpecification.java:256)
    at com.itextpdf.text.pdf.PdfDocument.addFileAttachment(PdfDocument.java:2253)
    at com.itextpdf.text.pdf.PdfWriter.addFileAttachment(PdfWriter.java:1714)
    at com.itextpdf.text.pdf.PdfStamper.addFileAttachment(PdfStamper.java:497)

Stacktrace を分析して調べてみるPdfFileSpecification.fileEmbedded と、EF が F および UF エントリで作成されていることがわかります。

PdfA3Checkerを見ると、その行PdfDictionary embeddedFile = getDirectDictionary(dict.get(PdfName.F));はディレクトリではなくストレムであることがわかります。

if (fileSpec.contains(PdfName.EF)) {
    PdfDictionary dict = getDirectDictionary(fileSpec.get(PdfName.EF));
    if (dict == null || !dict.contains(PdfName.F)) {
        throw new PdfAConformanceException(obj1, MessageLocalization.getComposedMessage("ef.key.of.file.specification.dictionary.shall.contain.dictionary.with.valid.f.key"));
    }

    PdfDictionary embeddedFile = getDirectDictionary(dict.get(PdfName.F));
    if (embeddedFile == null) {
        throw new PdfAConformanceException(obj1, MessageLocalization.getComposedMessage("ef.key.of.file.specification.dictionary.shall.contain.dictionary.with.valid.f.key"));
    }

    checkEmbeddedFile(embeddedFile);
}

これは iText のバグですか、それとも何か不足していますか? ちなみに私はiText 5.4.5を使っています。

更新 1

Bruno an mklが示唆するように、4.5.6-Snapshot には修正が含まれている必要があります。現在のトランクに対して、完全なテスト ケースへのテスト ケースの要旨リンクを試しました。しかし、結果は同じエラーでした。

4

2 に答える 2

3

「 PDF/A-3 の作成: 埋め込みファイルには有効な Params キーが含まれている必要があります」で焦点を当てたものと非常によく似たバグに遭遇しました。

問題は(あなたが見つけたように)このコードにあります

PdfDictionary embeddedFile = getDirectDictionary(dict.get(PdfName.F));
if (embeddedFile == null) {
    throw new PdfAConformanceException(obj1, MessageLocalization.getComposedMessage("ef.key.of.file.specification.dictionary.shall.contain.dictionary.with.valid.f.key"));
}

in PdfA3Checker.checkFileSpec(PdfWriter, int, Object); Fdictという名前のストリームが含まれていても、それを返しません。ただし、その理由は、ここでディクショナリが検索されているからではありません (ストリームは本質的に、いくつかの追加を加えたディクショナリです) 。getDirectDictionary(dict.get(PdfName.F))PdfAChecker.getDirectObjectPdfAChecker.getDirectDictionary

protected PdfObject getDirectObject(PdfObject obj) {
    if (obj == null)
        return null;
    //use counter to prevent indirect reference cycling
    int count = 0;
    while (obj.type() == 0) {
        PdfObject tmp = cachedObjects.get(new RefKey((PdfIndirectReference)obj));
        if (tmp == null)
            break;
        obj = tmp;
        //10 - is max allowed reference chain
        if (count++ > 10)
            break;
    }
    return obj;
}

このメソッドは、キャッシュされたオブジェクト (つまりcachedObjects) のみを検索しますが、あなたの場合 (および私のテストでも)、このストリームは既にファイルに書き込まれており、もうキャッシュにないため、null返される...修正、PPS を参照してください: 書き込まれましたが、そもそもキャッシュされていません

PS: PDF/A-3 準拠の添付ファイルは、PDF の作成中に ( を使用してPdfAWriter) 追加された場合は機能しますが、PDF の操作中に ( を使用してPdfAStamper) 追加された場合は機能しません。これらのユースケースでは、キャッシングが異なる場合があります。

PPS: 確かに違いがあります:追加されたオブジェクトをキャッシュに追加することでPdfAWriter、オーバーロードをオーバーライドします。はそうせず、さらに は からではなく と から派生します。addToBodyPdfAStamperImpPdfStamperImpPdfWriterPdfAWriter

于 2014-02-10T09:54:56.707 に答える