Quote of the Day

more Quotes

Categories

Buy me a coffee

Stamp a PDF using iTextSharp for .NET core

Published July 20, 2019 in .NET core , ASP.NET core - 1 Comment

Recently I had to implement the logic to “stamp” a PDF file in my ASP.NET core project. I found the sample codes from this SO post, which works greatly. I’ve extracted the logic into a sample project, which you can find on my github.

Some context

iText is a popular technology for working with PDF files. The current version as of this writing is iText7. However, the library is dual licensed as AGPL/Commercial, which mean you need to open source your project, or purchase the commercial license. The version which works with .NET core is iTextSharp.LGPLv2.Core which is free and what I use in the sample ASP.NET core project.

iTextSharp.LGPLv2.Core is an unofficial port of the last LGPL version of the iTextSharp (V4.1.6) to .NET Core

iTextSharp.LGPLv2.Core

For another example of using iTextSharp.LGPLv2.Core library, check out my post which shows how to fill out a PDF form using the library.

Install the library

dotnet add package iTextSharp.LGPLv2.Core

Model

public class StampRequestForm
   {
       public string Line1 { get; set; }
       public string Line2 { get; set; }
       public string Line3 { get; set; }
       public float LowerLeftX { get; set; }
       public float LowerLeftY { get; set; }
       public float UpperRightX { get; set; }
       public float UpperRightY { get; set; }
// ASP.NET core has support to bind a
// multipart/form-data request to a model
//via model binding using the IFormFile interface. [Required] public IFormFile Pdf { get; set; } public int RotationDegree { get; set; } }

For simplicity, I store each line of text in a separate field. Then I can just use ASP.NET core model binding to bind a file upload request nicely to the model, without having to do much work.

Service

 public interface IStampService
    {
        Stream ApplyStamp(StampRequestForm stampRequest);
    }

public class StampService : IStampService
    {
        private const int FontSize = 7;
        private readonly BaseFont Font = BaseFont.CreateFont();
        private readonly BaseColor Color = BaseColor.Red;
        private const int VerticalSpaceBetweenLines = 15;

        public StampService()
        {
        }

        /// <summary>
        /// Stamp a PDF with the specific message and position as specified in the <see cref="StampRequest"/>
        /// https://stackoverflow.com/questions/2372041/c-sharp-itextsharp-pdf-creation-with-watermark-on-each-page#
        /// </summary>
        /// <param name="stampRequest"></param>
        /// <returns></returns>
        public Stream ApplyStamp(StampRequestForm stampRequest)
        {
            MemoryStream pdfOutStream;
            Stream pdfInstream = null;
            PdfReader reader = null;
            PdfStamper stamper = null;
            try
            {
                pdfOutStream = new MemoryStream();
                pdfInstream = stampRequest.Pdf.OpenReadStream();
                reader = new PdfReader(pdfInstream);
                stamper = new PdfStamper(reader, pdfOutStream);
                var dc = stamper.GetOverContent(1);
                AddWaterMark(dc, reader, stampRequest);
                return pdfOutStream;
            }
            finally
            {
                if (pdfInstream != null)
                {
                    pdfInstream.Close();
                }
                if (reader != null)
                {
                    reader.Close();
                }
                if (stamper != null)
                {
                    stamper.Close();
                }
            }
        }

        private void AddWaterMark(PdfContentByte dc, PdfReader reader, StampRequestForm stampRequest)
        {
            var gstate = new PdfGState
            {
                FillOpacity = 0.61f,
                StrokeOpacity = 0.61f
            };
            dc.SaveState();
            dc.SetGState(gstate);
            dc.SetColorFill(Color);
            dc.BeginText();
            dc.SetFontAndSize(Font, FontSize);
            var x = (stampRequest.LowerLeftX + stampRequest.UpperRightX) / 2;
            var y = ((stampRequest.LowerLeftY + stampRequest.UpperRightY) / 2);
            var lines = new string[] {stampRequest.Line1, stampRequest.Line2,
                                      stampRequest.Line3}
            .Where(line => !string.IsNullOrEmpty(line));
            foreach (var line in lines)
            {
                dc.ShowTextAligned(Element.ALIGN_CENTER, line, x, y, stampRequest.RotationDegree);
                y -= VerticalSpaceBetweenLines;
            }
            dc.EndText();
            dc.RestoreState();
        }
    }

Controller

[Route("api/[controller]")]
   [ApiController]
   public class PDFController : Controller
   {
       private readonly IStampService _stampService; 

       public PDFController(IStampService stampService)
       {
           _stampService = stampService; 
       }

       [HttpPost]
       [Route("stamp")]
       [Produces(contentType: "application/pdf")]
       public FileStreamResult Stamp([FromForm] StampRequestForm stampRequestForm)
       { 
           Stream outStream = _stampService.ApplyStamp(stampRequestForm);
           outStream.Position = 0;
           return new FileStreamResult(outStream, "application/pdf");
       }

   }

Sample request

curl -X POST \
https://localhost:5001/api/pdf/stamp \
-H 'Postman-Token: d9016159-d9ac-4187-9291-6a0aac8a96c9' \
-H 'cache-control: no-cache' \
-H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
-F 'line1=This is a test stamp' \
-F line2=07/19/2019 \
-F line3=taithienbo.com \
-F LowerLeftX=402 \
-F LowerLeftY=600 \
-F UpperRightX=575 \
-F UpperRightY=900 \
-F pdf=@/PDFStampingExample/PDFStampingExample.Tests/Resources/sample.pdf

The above request applies the stamp near the top right.

Result

PDF stamping using iTextSharp LGPL .NET core
Stamp PDF using iTextSharp.LGPLv2.Core for .NET core

References

c# itextsharp PDF creation with watermark on each page

iTextSharp.LGPLv2.Core nuget package

1 comment