Java 1.8+PDFBox 2.0.18添加PDF/A合规元数据失败求助
解决PDFBox 2.0.18生成PDF/A时的元数据校验问题
我刚好在PDFBox 2.x版本里处理过一模一样的PDF/A元数据问题,给你一个经过验证的完整代码示例,同时帮你拆解之前踩过的坑:
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocumentCatalog; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.common.PDMetadata; import org.apache.pdfbox.pdmodel.graphics.color.PDDeviceRGB; import org.apache.xmpbox.XMPMetadata; import org.apache.xmpbox.schema.DublinCoreSchema; import org.apache.xmpbox.schema.PDFAIdentificationSchema; import org.apache.xmpbox.schema.XMPBasicSchema; import org.apache.xmpbox.xml.XmpSerializer; import java.io.ByteArrayOutputStream; import java.io.IOException; public class PDFAMetadataGenerator { public static void main(String[] args) throws IOException { // 初始化基础PDF文档(你已有这部分代码,可直接复用) try (PDDocument document = new PDDocument()) { PDPage page = new PDPage(); document.addPage(page); PDDocumentCatalog catalog = document.getDocumentCatalog(); // -------------------------- 核心元数据处理部分 -------------------------- // 1. 创建XMP元数据实例 XMPMetadata xmpMetadata = XMPMetadata.createXMPMetadata(); // 2. 添加PDF/A强制要求的标识Schema(以PDF/A-1b为例) PDFAIdentificationSchema pdfaSchema = xmpMetadata.createAndAddPFAIdentificationSchema(); pdfaSchema.setPart(1); // PDF/A版本,1对应PDF/A-1,2对应PDF/A-2 pdfaSchema.setConformance("B"); // 一致性等级,B为基本级 pdfaSchema.setAbout(""); // 必须设为空字符串!解决RDF About属性校验失败问题 // 3. 添加PDF/A必需的基础元数据Schema(缺一不可) // Dublin Core Schema:处理标题、作者等核心描述信息 DublinCoreSchema dcSchema = xmpMetadata.createAndAddDublinCoreSchema(); dcSchema.setTitle("我的PDF/A测试文档"); dcSchema.addCreator("Daniel Tung"); dcSchema.setAbout(""); // XMP Basic Schema:处理元数据的基础属性(至少要声明该Schema) XMPBasicSchema xmpBasicSchema = xmpMetadata.createAndAddXMPBasicSchema(); xmpBasicSchema.setAbout(""); // 4. 序列化XMP元数据,正确生成xpacket头 XmpSerializer serializer = new XmpSerializer(); ByteArrayOutputStream out = new ByteArrayOutputStream(); serializer.serialize(xmpMetadata, out, true); // withXpacket必须设为true,生成PDF/A要求的指令头 // 5. 将XMP元数据导入PDF文档的元数据流容器 PDMetadata documentMetadata = new PDMetadata(document); documentMetadata.importXMPMetadata(out.toByteArray()); catalog.setMetadata(documentMetadata); // -------------------------- 核心元数据处理结束 -------------------------- // 可选:如果你的文档还没处理颜色空间,添加RGB输出意图(PDF/A-1b要求) catalog.setOutputIntents(new PDPage(PDDeviceRGB.INSTANCE).getOutputIntents()); // 保存文档 document.save("valid-pdfa.pdf"); } } }
针对你遇到的错误的具体解释:
"Metadata is not a stream":
PDF/A标准强制要求元数据必须以PDF流的形式存储,你最开始没创建PDMetadata容器,直接跳过了这一步,上面代码中PDMetadata documentMetadata = new PDMetadata(document)就是用来创建这个流容器的。"xmp should start with a processing instruction":
当你设置serialize(..., false)时,输出的XMP没有包含PDF/A要求的<?xpacket begin="..."?>处理指令头,把第三个参数改成true就能自动生成这个头,符合校验要求。"Schemas not found..."和RDF About属性错误:
这是最容易踩的坑:- PDF/A要求必须同时包含
PDF/A Identification、Dublin Core、XMP Basic三个核心Schema,你之前只加了第一个,导致校验时提示缺少Schema; - 所有Schema的
about属性必须设为空字符串"",否则会触发RDF属性一致性校验失败,这是PDFBox 2.x版本PDF/A校验的硬性要求。
- PDF/A要求必须同时包含
额外提醒:
- 确保你的依赖里包含
xmpbox:2.0.18(和pdfbox版本完全一致),否则会出现兼容性问题; - 如果你需要生成PDF/A-2b,只需要把
pdfaSchema.setPart(1)改成setPart(2)即可,其他逻辑不变; - 你已经处理了其他校验问题(字体、颜色等),所以这个代码生成的文档应该能通过PDF/A校验。
内容的提问来源于stack exchange,提问作者Daniel Tung
相关产品推荐
相关产品推荐

