创建PDF/A-3:嵌入文件应包含有效的参数密钥
我正在尝试用itextpdf-5.4.5和itext-pdfa-5.4.5创建一个PDF/a-3。 设置PdfileSpecification时,会出现以下异常:创建PDF/A-3:嵌入文件应包含有效的参数密钥,pdf,itext,Pdf,Itext,我正在尝试用itextpdf-5.4.5和itext-pdfa-5.4.5创建一个PDF/a-3。 设置PdfileSpecification时,会出现以下异常: com.itextpdf.text.pdf.PdfAConformanceException: Embedded file shall contain valid Params key. 这是我创建PdfDictionary的部分: PdfDictionary params = new PdfDictionary(); params
com.itextpdf.text.pdf.PdfAConformanceException: Embedded file shall contain valid Params key.
这是我创建PdfDictionary的部分:
PdfDictionary params = new PdfDictionary();
params.put(PdfName.MODDATE, new PdfDate());
PdfFileSpecification fileSpec = PdfFileSpecification.fileEmbedded(
writer, "./src/main/resources/com/itextpdf/invoice.xml", "invoice.xml", null, false, "text/xml", params);
我找到了进行检查的方法,但没有找到任何解决方案:
com.itextpdf.text.pdf.internal.PdfA3Checker.checkEmbeddedFile
protected void checkEmbeddedFile(PdfDictionary embeddedFile) {
PdfDictionary params = getDirectDictionary(embeddedFile.get(PdfName.PARAMS));
if (params == null) {
throw new PdfAConformanceException(embeddedFile, MessageLocalization.getComposedMessage("embedded.file.shall.contain.valid.params.key"));
}
有什么想法吗?
提前谢谢你 大体上
PDF/A-3对嵌入式文件有一些特殊要求,其中
嵌入文件的流字典应包含Params键,其值应为至少包含ModDate键的字典,其值应为源文件的最新修改日期
(ISO 19000-3附录E.1)
iText support解释了如何从头开始创建符合PDF/A-3的PDF,并演示了如何以符合PDF/A-3的方式嵌入文件,示例代码:
PdfDictionary parameters = new PdfDictionary();
parameters.put(PdfName.MODDATE, new PdfDate());
PdfFileSpecification fileSpec = PdfFileSpecification.fileEmbedded(
writer, "./src/main/resources/com/itextpdf/invoice.xml",
"invoice.xml", null, "application/xml", parameters, 0);
fileSpec.put(new PdfName("AFRelationship"), new PdfName("Data"));
writer.addFileAttachment("invoice.xml", fileSpec);
PdfArray array = new PdfArray();
array.add(fileSpec.getReference());
writer.getExtraCatalog().put(new PdfName("AF"), array);
此示例还将关联的文件条目(AF)添加到目录中,这是另一个要求
顺便说一句,严格地说,参数字典只在应的基础上需要,而不是应。因此,这实际上是一个建议,在野外可能存在没有此条目的带有附件的有效PDF/a-3文档
尽管没有明显的理由说明为什么iText在创建PDF/A-3文件时不遵循这一建议会更好,但通过检查严格解释是可以的
iText 5.4.5中的问题
最近引入了OP发现的检查。将文件存储在PDF文件中时已触发此检查。不幸的是,此时尚未分配params字典,只保留了一个引用。因此,即使在编写词典不久之后,检查也会失败
从PdfFileSpecification.java
:
stream.put(PdfName.TYPE, PdfName.EMBEDDEDFILE);
stream.flateCompress(compressionLevel);
PdfDictionary param = new PdfDictionary();
if (fileParameter != null) {
param.merge(fileParameter);
}
if (!param.contains(PdfName.MODDATE)) {
param.put(PdfName.MODDATE, new PdfDate());
}
if (fileStore != null) {
param.put(PdfName.SIZE, new PdfNumber(stream.getRawLength()));
stream.put(PdfName.PARAMS, param);
}
else
stream.put(PdfName.PARAMS, refFileLength);
if (mimeType != null)
stream.put(PdfName.SUBTYPE, new PdfName(mimeType));
ref = writer.addToBody(stream).getIndirectReference();
在此操作过程中,检查发生(并失败)
在这里,紧接着,参数会被写入
变通办法
PdfFileSpecification.fileEmbedded
允许您将数据显示为字节[]
而不是文件系统中的文件。正如您在上面的源代码中看到的,在这种情况下处理不同:fileStore
包含byte[]
参数。如果您在那里继续使用文件存储
,您将看到,对于它的非null
值,params dictionary作为直接对象写入,因此出现在测试中
因此,如果您将文件作为
byte[]
实例提供,则可以将iText 5.4.5用于PDF/A-3文件附件。如果您使用iText-5.5.9,则还需要添加以下内容:
final PdfDictionary extraCatalog = writer.getExtraCatalog();
final PdfDictionary markInfoDict = new PdfDictionary();
markInfoDict.put(PdfName.MARKED, new PdfBoolean(true));
extraCatalog.put(PdfName.MARKINFO, markInfoDict);
否则,您将得到一个
PdfAConformanceException
说明如何在PDF/a-3的情况下正确附加文件。它是如何工作的?我用过它(当然是在iText 5.4.4中),它确实有效。谢谢,我试过了,但它不起作用。在我看来,本例中fileEmbedded方法的顺序不正确。我的itext版本需要以下顺序:-writer-filePath-fileDisplay-fileStore-compress-mimeType-fileparameter该方法有5个重载。因此,有多个正确的参数顺序。我假设在5.4.4和5.4.5之间引入了一个bug。谢谢您的解释。我将使用5.4.4,直到错误被解决:-)。@user3177193此问题已修复。该修复程序将在下一版本中提供。“因此,如果您将文件作为byte[]实例提供,则可以将iText 5.4.5用于PDF/A-3文件附件。”有人举过这样的例子吗,我没有看到一种方法在5.5中使用byte[]而不是字符串作为文件路径和文件名。8@user1567291 “在5.5.8中,我没有看到一种方法使用byte[]而不是字符串作为文件路径和文件名”-所有PdfFileSpecification.fileEmbedded
都有一个byte[]fileStore
参数,该参数记录为文件的字节数组。如果它不是null
则优先于filePath
。
final PdfDictionary extraCatalog = writer.getExtraCatalog();
final PdfDictionary markInfoDict = new PdfDictionary();
markInfoDict.put(PdfName.MARKED, new PdfBoolean(true));
extraCatalog.put(PdfName.MARKINFO, markInfoDict);