c# - 在旋转的文档上添加签名字段
问题描述
我正在尝试在旋转的文档上添加签名字段,但我不想在签名字段上应用旋转,它应该以 0 旋转添加到旋转页面上。
我尝试了以下方法,但它对我不起作用。
page.SetIgnorePageRotationForContent(true);
谁能提供这个问题的解决方案?
签名外观代码片段:
PdfFormXObject layer2Object = _pdfSignatureAppearance.GetLayer2();
PdfCanvas pdfCanvas = new PdfCanvas(layer2Object, _pdfSigner.GetDocument());
PdfPage page = _pdfSigner.GetDocument().GetPage(signingRequest.Page <= 0 ?
signingRequest.PageNumber : signingRequest.Page);
page = page.SetIgnorePageRotationForContent(false);
int pageRotation = page.GetRotation();
Canvas appearanceCanvas = new Canvas(pdfCanvas, _pdfSigner.GetDocument(),
layer2Object.GetBBox().ToRectangle());
ImageData signatureImageData =
ImageDataFactory.Create(signingRequest.SignatureImage);
Image signatureImage = new Image(signatureImageData);
signatureImageData.SetRotation(0f);
ImageData logoImageData =
ImageDataFactory.Create(Convert.FromBase64String(signingRequest.Logo));
Image logoImage = new Image(logoImageData);
logoImageData.SetRotation(0f);
KeyValuePair<string, SignatureAppearanceField> handSignatureKey = appearanceFieldSettings.Where(o => o.Key == SignatureAppearanceAttributes.HAND_SIGNATURE.ToString()).FirstOrDefault();
appearanceAttributes = new Paragraph().SetWidth(UnitValue.CreatePercentValue(100)).SetHeight(UnitValue.CreatePercentValue(100)).SetMargin(0.01f).SetStrokeWidth(0.1f);
handSignatureImage.SetHorizontalAlignment(iText.Layout.Properties.HorizontalAlignment.LEFT);
handSignatureImage = handSignatureImage.SetAutoScale(true);
handSignatureImage.SetMarginLeft((handSignatureKey.Value.X / aspectRatio) + 10);
if (appearanceFieldSettings.ContainsKey("COMPANY_LOGO"))
{
if (fieldSettings.Key == SignatureAppearanceAttributes.COMPANY_LOGO.ToString())
{
IList<Image> images = new List<Image>();
KeyValuePair<string, SignatureAppearanceField> companySignatureKey = appearanceFieldSettings.Where(o => o.Key == SignatureAppearanceAttributes.COMPANY_LOGO.ToString()).FirstOrDefault();
companyLogoImage.SetAutoScale(true);
companyLogoImage.SetHorizontalAlignment(iText.Layout.Properties.HorizontalAlignment.RIGHT);
companyLogoImage.SetMarginLeft((companySignatureKey.Value.Width / aspectRatio) - 20);
images.Add(handSignatureImage);
images.Add(companyLogoImage);
appearanceAttributes.AddAll(images);
if (pageRotation > 0)
{
handSignatureImage.SetRotationAngle((Math.PI / 180) * pageRotation);
companyLogoImage.SetRotationAngle((Math.PI / 180) * pageRotation);
appearanceAttributes.SetRotationAngle((Math.PI / 180) * pageRotation);
}
appearanceCanvas.Add(appearanceAttributes);
}
}
else
{
if (pageRotation > 0)
{
handSignatureImage.SetRotationAngle((Math.PI / 180) * pageRotation);
appearanceAttributes.SetRotationAngle((Math.PI / 180) * pageRotation);
}
appearanceAttributes.Add(handSignatureImage);
appearanceCanvas.Add(appearanceAttributes);
}
设置签名者和签名原因;
KeyValuePair<string, SignatureAppearanceField> signingReasonKey = appearanceFieldSettings.Where(o => o.Key == SignatureAppearanceAttributes.SIGNING_REASON.ToString()).FirstOrDefault();
string reason = !string.IsNullOrEmpty(signingRequest.WitnessReason) ? signingRequest.WitnessReason : signingRequest.SigningReason;
if (reason.Length > 25)
reason = reason.Substring(0, 25) + " ...";
Text signingReasonText = null;
appearanceAttributes = new Paragraph().SetFontSize(signingReasonKey.Value.Font.FontSize / aspectRatio).SetMargin(0.01f).SetStrokeWidth(0.1f);
if (signingReasonKey.Value.ShowLabel)
{
signingReasonText = new Text(signingReasonKey.Value.LabelName + ": " + reason);
}
else
{
signingReasonText = new Text(reason);
}
if (pageRotation > 0)
{
appearanceAttributes.SetRotationAngle((Math.PI / 180) * pageRotation);
}
appearanceAttributes.Add(signingReasonText);
appearanceCanvas.Add(appearanceAttributes);
解决方案
我使用了您的示例文件中的修订版,它有两个空的签名字段并且尚未签名。此外,我使用了您签名图像的重建版本。
使用 iText 默认外观
作为第一次检查,我应用了常规 iText 签名代码,其中 iText 本身填充了签名的外观:
using (PdfReader pdfReader = new PdfReader(PDF_SOURCE))
{
PdfSigner pdfSigner = new PdfSigner(pdfReader, File.Create(PDF_DEST), new StampingProperties().UseAppendMode());
ImageData imageData = ImageDataFactory.Create(IMAGE_SOURCE);
pdfSigner.SetFieldName("SH_SIGNATURE_417868");
PdfSignatureAppearance sigAppearance = pdfSigner.GetSignatureAppearance();
sigAppearance.SetContact("ContactInfo");
sigAppearance.SetLocation("Location");
sigAppearance.SetReason("SigningReason");
sigAppearance.SetLayer2Text("Muddassir Awan");
sigAppearance.SetSignatureGraphic(imageData);
sigAppearance.SetRenderingMode(RenderingMode.GRAPHIC_AND_DESCRIPTION);
sigAppearance.SetSignatureCreator("Muddassir Awan");
int estimatedSize = 12000;
pdfSigner.SignExternalContainer(new ExternalBlankSignatureContainer(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached), estimatedSize);
}
结果:
因此,这是可行的。
但是,显然,您希望数据以不同的方式排列,因此我们必须尝试在本质上与 iText 的外观生成代码相同,只是组件的排列方式不同。
使用自定义外观
由于 iText 代码有效(如上所示)并且您的代码引用了我在此处没有的许多变量,因此我从头开始编写此代码,从 iText 借用代码(PdfSignatureAppearance.GetAppearance()
更准确地说),旨在创建有点类似于您的非旋转文档的屏幕截图:
using (PdfReader pdfReader = new PdfReader(PDF_SOURCE))
{
PdfSigner pdfSigner = new PdfSigner(pdfReader, File.Create(PDF_DEST), new StampingProperties().UseAppendMode());
ImageData signatureImageData = ImageDataFactory.Create(IMAGE_SOURCE);
Image signatureImage = new Image(signatureImageData);
pdfSigner.SetFieldName("SH_SIGNATURE_417868");
PdfSignatureAppearance sigAppearance = pdfSigner.GetSignatureAppearance();
sigAppearance.SetContact("ContactInfo");
sigAppearance.SetLocation("Location");
sigAppearance.SetReason("SigningReason");
sigAppearance.SetSignatureCreator("Muddassir Awan");
PdfPage page = pdfSigner.GetDocument().GetPage(sigAppearance.GetPageNumber());
int rotation = page.GetRotation();
PdfFormXObject layer2Object = sigAppearance.GetLayer2();
Rectangle rect = layer2Object.GetBBox().ToRectangle();
PdfCanvas pdfCanvas = new PdfCanvas(layer2Object, pdfSigner.GetDocument());
if (rotation == 90)
pdfCanvas.ConcatMatrix(0, 1, -1, 0, rect.GetWidth(), 0);
else if (rotation == 180)
pdfCanvas.ConcatMatrix(-1, 0, 0, -1, rect.GetWidth(), rect.GetHeight());
else if (rotation == 270)
pdfCanvas.ConcatMatrix(0, -1, 1, 0, 0, rect.GetHeight());
Rectangle rotatedRect = 0 == (rotation / 90) % 2 ? new Rectangle(rect.GetWidth(), rect.GetHeight()) : new Rectangle(rect.GetHeight(), rect.GetWidth());
Canvas appearanceCanvas = new Canvas(pdfCanvas, pdfSigner.GetDocument(), rotatedRect);
Paragraph text = new Paragraph();
text.SetFontSize(7).Add("Signed by: Muddassir Awan\nReason: I approve this document\nSigned at: 2020-02-20 16:55:20 +05:00");
appearanceCanvas.Add(text);
signatureImage.ScaleToFit(rotatedRect.GetWidth(), 40);
appearanceCanvas.Add(signatureImage);
int estimatedSize = 12000;
pdfSigner.SignExternalContainer(new ExternalBlankSignatureContainer(PdfName.Adobe_PPKLite, PdfName.Adbe_pkcs7_detached), estimatedSize);
}
结果:
这大约是您想要的,除了位置微调。
因此,只需将旋转变换应用于PdfCanvas
抵消页面旋转,然后Canvas
根据该旋转选择矩形。
推荐阅读
- python - 从 python Opencv Videocapture 接收 Gazebo gstreamer UDP 视频
- sql - 给定日期 2019-12-31 过去 3 个月的 yyyymm 格式日期列表
- vba - How to change the background color of the cell content?
- python-3.x - 推荐使用 pydbus 或 dbus-python 有什么区别?
- android - 如何计算 Kotlin 中最近一次登录和 180 天会话到期日期的剩余天数?
- php - 删除多个项目数组而不破坏键 PHP 的顺序
- angular - Angular Frontend on azure isn't reloaded on mobile when a new main is pushed
- c++ - ZeroMQ: How to cast a pollitem_t item, used in Poller, back to a ZeroMQ socket?
- android - 适用于 Android 的 ARCore
- c# - UWP/Windows 10 场景 - 如何使用 Launcher 类启动多个图像打开多个照片窗口?