c# - 使用附加模式属性后,iText7 将签名转换为不可见签名
问题描述
我遇到的问题是,如果我在文档中创建签名字段时使用UseAppendMode属性,则在签名时会创建不可见的签名。否则,它会显示我的自定义签名外观的内容并在 PDF 中创建一个可见的签名。以下是我的代码片段:
SigningResponse signingResponse = new SigningResponse();
Stream outputStream = new MemoryStream();
Org.BouncyCastle.X509.X509Certificate x509Certificate = null;
int estimatedSize = SigningProfile.ContainsKey(ProfileCommon.DICTIONARY_SIZE.ToString()) ?
int.Parse(SigningProfile[ProfileCommon.DICTIONARY_SIZE.ToString()]) * 1024 : 600 * 1024;
Stream readerStream = new MemoryStream(documentBytes);
PdfReader pdfReader = new PdfReader(readerStream);
PdfSigner pdfSigner = new PdfSigner(pdfReader, outputStream, new StampingProperties().UseAppendMode());
pdfSigner.SetFieldName("Signature1");
pdfSigner.GetDocument().GetCatalog().SetModified();
if (signingRequest.CertifyPolicy != (int)CertifyPolicy.NOT_CERTIFIED)
pdfSigner.SetCertificationLevel(signingRequest.CertifyPolicy);
PdfSignatureAppearance signatureAppearance = pdfSigner.GetSignatureAppearance();
signatureAppearance.SetContact("Contact Info");
signatureAppearance.SetLocation("Location");
signatureAppearance.SetPageNumber(1);
signatureAppearance.SetReason("Signing Reason");
PdfFormXObject n0 = signatureAppearance.GetLayer0();
float x = n0.GetBBox().ToRectangle().GetLeft();
float y = n0.GetBBox().ToRectangle().GetBottom();
float width = n0.GetBBox().ToRectangle().GetWidth();
float height = n0.GetBBox().ToRectangle().GetHeight();
PdfCanvas canvas = new PdfCanvas(n0, pdfSigner.GetDocument());
canvas.SetFillColor(ColorConstants.LIGHT_GRAY);
canvas.Rectangle(x, y, width, height);
canvas.Fill();
// Set the signature information on layer 2
PdfFormXObject n2 = signatureAppearance.GetLayer2();
Paragraph p = new Paragraph("This document was signed by Bruno Specimen.");
new Canvas(n2, pdfSigner.GetDocument()).Add(p);
signatureAppearance.SetCertificate(x509Certificate);
PreSigning external = new PreSigning(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached);
pdfSigner.SignExternalContainer(external, estimatedSize);
signingResponse.DocumentHash = external.getHash();
signingResponse.D2S = signingResponse.DocumentHash;
signingResponse.DocumentBytes = ((MemoryStream)outputStream).ToArray();
return signingResponse;
并且创建签名字段的代码如下:
byte[] documentBytes = null;
foreach (PDFSignatureField field in signatureFields)
{
using (Stream memoryStream = new MemoryStream())
using (PdfReader _pdfReader = new PdfReader(new MemoryStream(_documentBytes)).SetUnethicalReading(true))
using (PdfDocument pdfDocument = new PdfDocument(_pdfReader, new PdfWriter(memoryStream)))
{
PdfAcroForm pdfAcroForm = PdfAcroForm.GetAcroForm(pdfDocument, true);
//Initializing signature position object
PDFSignaturePosition SigPosition = field.Position;
for (int i = 0 ; i < SigPosition.Pages.Length ; ++i)
{
//Getting PDF document page
PdfPage page = pdfDocument.GetPage(SigPosition.Pages[i]);
if (page == null)
{
page = pdfDocument.GetPage(SigPosition.PageNumber);
}
//Getting PDF document page rotation
int rotation = page.GetRotation();
//Getting signature field rects according to PDF page
iText.Kernel.Geom.Rectangle rect;
if (rotation > 0 && SigPosition.Position == PDFSignaturePosition.DefaultSignaturePosition.Custom)
{
rect = GetSignaturePositionAccordingToRotation(SigPosition.Rect, page.GetCropBox(), rotation);
}
else
{
rect = GetSignaturePositionRect(SigPosition.Position, SigPosition.Rect, page.GetCropBox());
}
//Creating signature field into PDF page
PdfFormField sig = PdfFormField.CreateSignature(pdfDocument, rect);
//Setting signature field visible flag
if (field.Display == (int)SignatureDisplayType.INVISIBLE)
{
sig.SetFieldFlags(PdfFormField.HIDDEN);
sig.SetVisibility(PdfFormField.HIDDEN);
}
else
{
sig.SetFieldFlags(PdfFormField.VISIBLE);
}
//Setting signature field font information
sig.Put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g"));
//Setting signature field name
sig.SetFieldName(i == 0 ? field.Name : field.Name + " - " + SigPosition.Pages[i]);
//Setting signature field page
sig.SetPage(SigPosition.Pages[i]);
//Adding signature field into AcroForm
pdfAcroForm.AddField(sig, page);
//Making indirect reference of the added signature field into PDF
sig.MakeIndirect(pdfDocument);
//Closing PDF document object
pdfDocument.Close();
//Getting latest document bytes after adding PDF field
documentBytes = ((MemoryStream)memoryStream).ToArray();
if (i + 1 == SigPosition.Pages.Length)
{
break;
}
}
_documentBytes = documentBytes;
}
}
解决方案
由于您在显示的代码之外使用了许多定义、声明和填充的变量,因此我不得不大大减少您的代码。此外,我没有要测试的示例文档,因此必须使用我手头的文档进行测试。
尽管如此,我可以重现该问题并在我的设置中找到解决方案。我希望尽管设置存在所有差异,但您可以使用此解决方案。
签名字段在我的设置中变得不可见的原因是,在以追加模式将签名字段添加到文档时,文档范围的AcroForms字典中的Fields数组未标记为已修改。另一方面,签名者依靠签名字段来签名,以便在该Fields数组中找到。因此,签名者没有找到准备好的可见字段,并使用该名称创建了一个新的不可见字段。
一种解决方法是手动将有问题的数组标记为已修改:
pdfAcroForm.GetPdfObject().Get(PdfName.Fields).SetModified();
pdfAcroForm.GetPdfObject().SetModified();
//Closing PDF document object
pdfDocument.Close();
推荐阅读
- scala - 在 Scala 中声明 var 不是 null 或 None
- javascript - 如何在我的字符串长度计数中包含非 spintax 内容?
- python - 在日期列的选择性时间段中添加 1 天
- ios - 如何修复:“致命错误:在隐式展开可选值时意外发现 nil”
- java - 如何从 bytearray 创建 unicode 字符串
- android - 使用 ViewPager2 获取当前片段
- zend-framework3 - Zend 框架 3 路由器在单独的文件中(不在配置数组树中)
- r - 我的数据是否适合嵌套的方差分析/线性混合效应模型,应该如何编写公式?
- python - 比较“float('nan')”和“math.nan”
- c# - ASMX Webservice - 启用 HTTP POST [405 方法不允许]