You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ZUGFeRD Mustang Validator报字体引用相关Resources字典缺失错误排查求助

ZUGFeRD Mustang Validator报字体引用相关Resources字典缺失错误排查求助

大家好,我们团队正在德国推行基于ZUGFeRD和PDF/A标准的电子发票落地,但在验证环节遇到了一个棘手的问题,想请各位帮忙分析下原因。

我们用Mustang Validator验证一份结构非常简单的PDF时,得到了如下错误结果:

<?xml version="1.0" encoding="UTF-8"?>

<validation filename="Beleg_245210299_20241201_out.pdf" datetime="2025-02-14 13:16:52">
  <pdf>ValidationResult [flavour=3u, totalAssertions=695, assertions=[TestAssertion [ruleId=RuleId [specification=ISO 19005-3:2012, clause=6.2.2, testNumber=2], status=failed, message=A content stream that references other objects, such as images and fonts that are necessary to fully render or process the stream, shall have an explicitly associated Resources dictionary as described in ISO 32000-1:2008, 7.8.3, location=Location [level=CosDocument, context=root/document[0]/pages[0](9 0 obj PDPage)/contentStream[0](14 0 obj PDContentStream)/operators[0]/xObject[0]/contentStream[0](17 0 obj PDContentStream)], locationContext=null, errorMessage=A content stream refers to resource(s) F1 not defined in an explicitly associated Resources dictionary]], isCompliant=false]
    <info>
      <signature>unknown</signature>
      <duration unit="ms">652</duration>
    </info>
    <summary status="invalid"/>
  </pdf>  
  <xml>
    <info>
      <version>2</version>
      <profile>urn:cen.eu:en16931:2017</profile>
      <validator version="2.16.2"/>
      <rules>
        <fired>177</fired>
        <failed>0</failed>
      </rules>
      <duration unit="ms">1270</duration>
    </info>
    <summary status="valid"/>
  </xml>
  <summary status="invalid"/>
</validation>

我们偶然发现了一个关键现象:只要把PDF里的页眉“Blatt: 1 von 1”删掉,这个验证错误就完全消失了。所以我们推测问题应该和页眉部分的字体引用逻辑有关,但暂时还没找到具体原因。

补充下相关背景:

  • 我们的源PDF包含上述页眉内容,后续用PDFBox将标准ZUGFeRD XML嵌入进去,生成了待验证的目标PDF/A文件
  • 验证时使用的命令是:
$ java  -jar Mustang-CLI-2.16.2.jar --action validate --no-notice --source Beleg_245210299_20241201_out.pdf

错误提示里的核心问题是:

A content stream that references other objects, such as images and fonts that are necessary to fully render or process the stream, shall have an explicitly associated Resources dictionary as described in ISO 32000-1:2008

我们查了相关的PDF/A技术文档,但里面的内容并没有给出有效的排查方向。

以下是我们用来嵌入ZUGFeRD XML的Java代码:

首先是核心的文件嵌入方法:

private void attachFile(String filename, String relationship, String description, String subType, byte[] data) throws IOException {
    this.fileAttached = true;

    PDComplexFileSpecification fs = new PDComplexFileSpecification();
    fs.setFile(filename);

    COSDictionary dict = fs.getCOSObject();
    dict.setName("AFRelationship", relationship);
    dict.setString("UF", filename);
    dict.setString("Desc", description);

    ByteArrayInputStream bais = new ByteArrayInputStream(data);
    PDEmbeddedFile ef = new PDEmbeddedFile(pdf, bais);
    ef.setSubtype(subType);
    ef.setSize(data.length);
    ef.setCreationDate(Calendar.getInstance());
    ef.setModDate(Calendar.getInstance());

    fs.setEmbeddedFile(ef);
    dict = fs.getCOSObject();

    COSDictionary efDict = (COSDictionary) dict.getDictionaryObject(COSName.EF);
    COSBase lowerLevelFile = efDict.getItem(COSName.F);
    efDict.setItem(COSName.UF, lowerLevelFile);

    PDDocumentNameDictionary names = new PDDocumentNameDictionary(pdf.getDocumentCatalog());
    PDEmbeddedFilesNameTreeNode efTree = names.getEmbeddedFiles();
    if (efTree == null) {
        efTree = new PDEmbeddedFilesNameTreeNode();
    }

    Map<String, PDComplexFileSpecification> namesMap = new HashMap<>();
    Map<String, PDComplexFileSpecification> oldNamesMap = efTree.getNames();
    if (oldNamesMap != null) {
        namesMap.putAll(oldNamesMap);
    }

    namesMap.put(filename, fs);
    efTree.setNames(namesMap);
    names.setEmbeddedFiles(efTree);
    pdf.getDocumentCatalog().setNames(names);

    COSBase afEntry = pdf.getDocumentCatalog().getCOSObject().getItem("AF");
    COSArray cosArray;
    if (afEntry == null) {
        cosArray = new COSArray();
        cosArray.add(fs);
        pdf.getDocumentCatalog().getCOSObject().setItem("AF", cosArray);
    } else if (afEntry instanceof COSArray) {
        cosArray = (COSArray) afEntry;
        cosArray.add(fs);
        pdf.getDocumentCatalog().getCOSObject().setItem("AF", cosArray);
    } else {
        if (!(afEntry instanceof COSObject) || !(((COSObject) afEntry).getObject() instanceof COSArray)) {
            throw new IOException("Unexpected object type for PDFDocument/Catalog/COSDictionary/Item(AF)");
        }
        cosArray = (COSArray) ((COSObject) afEntry).getObject();
        cosArray.add(fs);
    }
}

然后是调用这个方法的代码:

this.attachFile(filename, "Alternative",
        "Invoice metadata conforming to ZUGFeRD standard",
        "text/xml", this.xmlProvider.getData());

想请教各位,为什么Mustang Validator会抛出这个Resources字典缺失的错误?有没有什么排查方向或者解决方案可以参考?

备注:内容来源于stack exchange,提问作者TheSmoun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 10:08:05