Blazor Signature to Sing a PDF Document

Blazor signature

In this post, I demonstrate how to add a signature to a PDF using the Blazor Server.

The objective is to guide you in writing a signature in a PDF document. The project is online at https://blazorSignature.jsmotta.com/sign.

This interface allows you to draw your signature with the mouse or fingers on mobile devices.

Pdf sign

This is a practical post and is not intended to elucidate all technologies (Blazor Server, Telerik UI for Blazor, Telerik Documents libraries, and NuGet) involved in this project.

Let’s do it!

Starting with Visual Studio in Extensions -> Telerik -> Telerik UI for Blazor -> Create new Telerik Project, follow the instructions.

  • Choose the best location for your project.
  • I selected the Server and Admin template.
  • Open NuGet on the solution and add these Telerik Components.

The Code

We start adding the TelerikSignature, the control that interacts with the user to draw the signature.

The name of who is singing is read in the input TelerikTextBox.

<div id="about" class="k-d-flex-col k-justify-content-between k-align-items-start" style="margin:2em; width:60%;">
    <h2>Pdf Sign</h2>
    <br />
    <label label-for="MyName">Your Name:</label><br />
    <TelerikTextBox @bind-Value="@MyName"></TelerikTextBox>
    
    <br/>
    
    <p>Draw your signature.</p>
    
    <TelerikSignature @bind-Value="@SignatureValue"
                      Width="@(PWidth+("px"))"
                      Height="@(PHeight+("px"))" />
</div>
Here, we draw the preview on the screen according to the emptiness of SignatureValue. This is only for this sample:
@if (!string.IsNullOrEmpty(SignatureValue))
{
    <div class="k-d-flex-col k-justify-content-between k-align-items-start" style="margin:2em; width:60%;">
        <p><TelerikButton OnClick="@SignPdf">Sign Document</TelerikButton></p>
        @if (!string.IsNullOrEmpty(UrlSignedPdf))
        {
            <a class="telerik-blazor k-button k-button-solid k-rounded-md k-button-md k-button-solid-base" href="@UrlSignedPdf" target="_blank"><span class="k-buttom-text">Download</span></a>
        }

        <h2>Signature Value</h2>

        <img alt='Signature' src="@SignatureValue" width="@PWidth" height="@PHeight" />
    </div>
}

Below is the code that does the magic on SingPdf(). Here are the steps.

  1. Lines 15 and 16 establish compatibility.
  2. Assigned unique names to the files, PDFs, and images;
  3. Accessed the template PdfSample.pdf from wwwroot\Pdfs at line 28.
  4. Line 39 imports the PDF document. Line 47 defines the last page to be drawn.
  5. Specified a position to draw on line 60.
  6. Drew MyName on line 61.
  7. The signature was rendered at line 66.
  8. Exported to the new file at line 70.
  9. Line 76 specifies the route for downloading the link.
@code {

    // Initialized the variables

    const int PWidth = 500; // Default width
    const int PHeight = 150; // Default height
    private string MyName { get; set; } = "Your Name";
    private string SignatureValue { get; set; } = string.Empty;
    private string UrlSignedPdf { get; set; } = string.Empty;
    private const string PngBase64Prefix = "data:image/png;base64,";

    async Task SignPdf()
    {
        // .NET 6 removed the System.Drawing.Common package, so we need to use the Telerik.Documents.ImageUtils package to work with images
        FixedExtensibilityManager.ImagePropertiesResolver = new Telerik.Documents.ImageUtils.ImagePropertiesResolver();
        FixedExtensibilityManager.JpegImageConverter = new Telerik.Documents.ImageUtils.JpegImageConverter();

        // Generate unique file names for the signature image and the signed PDF document
        var tickUniq = DateTime.Now.Ticks;
        var signaturePdfFileName = $@"\Pdfs\signature_{tickUniq}.pdf";
        var signaturePngFileName = HostingEnvironment.WebRootPath + $@"\\Signatures\\ignature_{tickUniq}.png";

        var filePdf2Sign = HostingEnvironment.WebRootPath + @"\\Pdfs\\PdfSample.pdf";

        // Save the signature image to a file
        var imageBytes = Convert.FromBase64String(SignatureValue[PngBase64Prefix.Length..]);

        await using (var imageFile = new FileStream(signaturePngFileName, FileMode.Create))
        {
            await imageFile.WriteAsync(imageBytes, 0, imageBytes.Length);
            await imageFile.FlushAsync();
        }

        // Load the PDF document
        var provider = new PdfFormatProvider();
        RadFixedDocument document;
        await using (Stream input = System.IO.File.OpenRead(filePdf2Sign))
        {
            document = provider.Import(input);
        }

        // Add the signature to the last page of the document

        await using (var source = System.IO.File.Open(signaturePngFileName, FileMode.Open))
        {
            var imageSource = new ImageSource(source);
            var lastPage = document.Pages.Last();
            var editor = new FixedContentEditor(lastPage);

            // Add the signature to the last page of the document
            var textFragment = new TextFragment(MyName)
            {
                Font = FontsRepository.HelveticaBoldOblique,
                FontSize = 14,
                Fill = new Telerik.Windows.Documents.Fixed.Model.ColorSpaces.RgbColor(0, 0, 0)
            };

            // Set the position of the MyName
            var size = new Telerik.Documents.Primitives.Size(PWidth, PHeight);
            editor.Position.Translate(offsetX: 150, offsetY: 800);
            editor.DrawText(MyName);
            
            // Set the position of the signature
            editor.Position.Translate(offsetX: 150, offsetY: textFragment.FontSize + 10 + 800); 
            
            editor.DrawImage(imageSource, size);
        }

        // Save the signed PDF document
        await using (var pdfStream = System.IO.File.Create(HostingEnvironment.WebRootPath + signaturePdfFileName))
        {
            provider.Export(document, pdfStream);
        }

        // Set the URL of the signed PDF document
        UrlSignedPdf = signaturePdfFileName.Replace("\\", "/")[1..];

    }

}

Conclusion

It was not easy to do without a sample at the beginning, but now I've included the source to make it easier. Feel free to access it on my GitHub: https://github.com/jssmotta/TelerikBlazorSignature24.


Similar Articles