温馨提示:本文翻译自stackoverflow.com,查看原文请点击:c# - Add signature field on rotated document
.net c# itext7 pdf

c# - 在旋转的文档上添加签名字段

发布于 2020-05-13 01:54:25

我正在尝试在旋转的文档上添加签名字段,但我不想在签名字段上应用旋转,因此应将其添加到旋转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);

在此处输入图片说明

查看更多

提问者
Muddassir Awan
被浏览
69
mkl 2020-03-09 20:33

我使用了示例文件中的修订版,其中包含两个空的签名字段,并且尚未签名。此外,我使用了签名图像的重建版本。

使用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根据该旋转选择矩形。