2015-10-22 36 views
2

所以我想签署一个PDF/A-1A文档,该文档是使用ITextSharp生成的。当我在文件上签名,并尝试验证文件我碰到下面的错误,ITextSharp签署PDF/A文档

验证文件“test_pdfA_compliance_signed.pdf”一致性水平PDFA-1A 所要求XMP财产“pdfaid:部分”缺失。 缺少必需的XMP属性'pdfaid:conformance'。 一个字符串长于65535字节。 该文件不符合要求的标准。 该文档不符合PDF参考(缺少必需的条目,错误的值类型等)。 文档的元数据缺失或不一致或损坏。 完成。

文件预签名:签名后https://drive.google.com/file/d/0B9RyqgJoa6W8UDFSeHJSX09QamM/view?usp=sharing

文件:https://drive.google.com/file/d/0B9RyqgJoa6W8Y3lGbFU4a2RsLWc/view?usp=sharing

但按预期的方式完成了签约过程,但我已经意识到了,如果我测试是否该文件宣称是PDF/A兼容的,如果没有元数据声称PDF/A失败,

private bool CreatePdfStamperIsPDFADocument(PdfReader reader) 
    { 
     if (reader.Metadata != null && reader.Metadata.Length > 0) 
     { 
      IXmpMeta xmpMeta = XmpMetaParser.Parse(reader.Metadata, null); 
      IXmpProperty pdfaidConformance = xmpMeta.GetProperty(XmpConst.NS_PDFA_ID, "pdfaid:conformance"); 
      IXmpProperty pdfaidPart = xmpMeta.GetProperty(XmpConst.NS_PDFA_ID, "pdfaid:part"); 

      if (pdfaidConformance == null || pdfaidPart == null) 
      { 
       return false; 
      } 
     } 

     return true; 
    } 

我曾经签署该文件的代码,该PDF压模我们由于检查失败,这里编辑是正常的。当我尝试使用PDFAStamper时,它抱怨说只能使用PDF/A文档。

private byte[] SignDocument(Certificate certificate, SigningInformation information, List<SigningBlock> signingBlocks, List<MemberItemSignature> signatureImages, byte[] document, bool certify) 
    { 
     for (int i = 0; i < signingBlocks.Count; i++) 
     { 
      using (MemoryStream outputStream = new MemoryStream()) 
      { 
       using (PdfReader reader = new PdfReader(document)) 
       { 
        using (PdfStamper stamper = CreatePdfStamper(reader, outputStream, true)) 
        { 
         SigningBlock signingBlock = signingBlocks[i]; 
         PdfSignatureAppearance appearance = CreatePdfAppearance(stamper, information, certify && i == 0); 

         SignDocumentSigningBlock(certificate, information, signingBlock, appearance, stamper, GetSignatureImage(signatureImages, signingBlock.Name)); 
        } 
       } 

       document = outputStream.ToArray(); 
      } 
     } 

     return document; 
    } 

因此,这是我决定使用哪个PDF压模的代码,但是这是因为使用的返回null,因为我用它来确定PDF/A要求两个组件文档IM哪里失败,

 private PdfStamper CreatePdfStamper(PdfReader reader, MemoryStream outputStream, bool isSignature) 
    { 
     if (isSignature) 
     { 
      if (CreatePdfStamperIsPDFADocument(reader)) 
      { 
       return PdfAStamper.CreateSignature(reader, outputStream, _pdfVersion, null, true, PdfAConformanceLevel.PDF_A_1A); 
      } 
      else 
      { 
       return PdfStamper.CreateSignature(reader, outputStream, _pdfVersion, null, true); 
      } 
     } 
     else 
     { 
      return new PdfStamper(reader, outputStream, _pdfVersion, true); 
     } 
    } 

我在做一些愚蠢的事情或缺少一些小事? 谢谢你的帮助。

亲切的问候

+0

考虑使用PDF/A的特定iTextSharp的类,如'PdfAStamper'。您可能必须在PDF/A相关的iTextSharp随播库中添加依赖项。 – mkl

+0

我确实使用PDF/A特定类,问题是PdfAStamper抛出一个异常,指出它不是一个试图加载的PDF/A文档。我调查了为什么,并在代码示例pdfaidConformance以及pdfaidpart为null。 – Johandre

回答

2

当使用常规PdfStamper,iTextSharp的不作企图使你的输出文件的PDF/A标准。特别是,它不会添加任何PDF/A相关的元数据。因此,预计您对元数据(CreatePdfStamperIsPDFADocument())的测试会为签名文档返回false

当运行在你的输入文件的代码示例,它返回true,与pdfaidPart等于1pdfaidConformance等于A。这是调试器显示在运行代码:

pdfaid values

为了得到一个PDF/A输出文件,你必须使用PdfAStamper。你说PdfAStamper给你一个有关你的输入文件不是PDF/A的错误。这可能是因为您正在指定与您的输入文件不同的PDF/A部分和/或一致性级别。 PdfAStamper不会将PDF/A输入文件转换为不同的部件或一致性级别。

因此,请确保您的PDF/A-1A输入创建PdfAStamper

PdfStamper stamper = PdfAStamper.CreateSignature(reader, outputfile, 
    '\0', PdfAConformanceLevel.PDF_A_1A); 
+0

mmm这真的很奇怪,对我来说,它对两个组件返回null,即pdfaidPart和pdfaidConformance。所以我正在使用PDFAStamper,并且用相关的代码片段更新了这个问题。从代码片段中,你可以看到我做了一个检查,如果它是PDF/A文档,它使用PDFAStamper,否则使用正常的压模,但对于我来说,if语句失败,这是我的问题。由于5.5.7中的签名错误,我使用ITextSharp 5.5.6 – Johandre

+0

我已经使用您的确切代码示例,您的* Pre-Signed * PDF和iTextSharp 5.5.6再次进行了测试。行为仍然如预期。我将用调试器屏幕截图更新我的答案。 – rhens

+1

我不知道我的VisualStudio做了什么,但是今天当我运行与昨天完全相同的代码时,代码按预期工作,并且我得到了与您一样的结果。唯一的区别是我重新启动我的VS,不知道那里发生了什么:O.Thanks的反应和帮助:) – Johandre