Create PDF Documents

You can create PDF documents programmatically by adding text, images and other types of elements. The generated PDF can be saved either in memory or as a file and can be further processed using the PdfEditor component. You can enhance the generated PDF by adding security features such as encryption, permissions or a digital signature as well as custom headers and footers or visual elements like stamps and shapes.

A PDF document created from scratch is represented by the Winnovative.Pdf.NextPdfDocument class, which allows you to add various PDF elements using a simple interface. For example, it provides the PdfDocumentAddText(PdfTextElement) method to add a text element to the current page of the document or the PdfDocumentAddImage(PdfImageElement) method to add an image element to the current page of the PDF.

Create, Render Elements and Save PDF Documents

A PdfDocument can be created with the default options using the PdfDocument constructor without parameters. This creates a PDF document with A4 portrait page size and no margins. The constructor also adds an empty page to the PDF document.

Create a PDF Document with Default Settings
// Create a new PDF document with the default settings
using PdfDocument pdfDocument = new PdfDocument();

To create a PDF document with custom page size, orientation and margins, use the PdfDocument(PdfDocumentCreateSettings) constructor, which accepts a Winnovative.Pdf.NextPdfDocumentCreateSettings parameter where you can specify these options. The example below demonstrates how to create a PDF document with custom settings.

Create a PDF Document with Custom Settings
PdfDocumentCreateSettings pdfCreateSettings = new PdfDocumentCreateSettings()
{
  PageSize = PdfPageSize.A4,
  PageOrientation = PdfPageOrientation.Portrait,
  Margins = new PdfMargins(36, 36, 36, 36)
};

// Create a new PDF document with the specified settings
using PdfDocument pdfDocument = new PdfDocument(pdfCreateSettings);

Add New PDF Pages

The PdfDocument constructor automatically adds the first page to the document, where you can begin adding elements.

You can add new PDF pages using the PdfDocumentAddPage method. The new page will use the current page size, orientation and margins defined when the document was created. The example below shows how to add a new page using the current settings.

Add a New PDF Page
// Add a new PDF page with current settings
pdfDocument.AddPage();

You can change the page settings before adding a new page by using the PdfDocumentSetPageSize(PdfPageSize, PdfPageOrientation) method and the PdfDocumentMargins property. The example below adds an A4 landscape page with all margins set to 100 points.

Add a New PDF Page with Updated Settings
// Set the next page to landscape A4
pdfDocument.SetPageSize(PdfPageSize.A4, PdfPageOrientation.Landscape);

// Set the next page margins
pdfDocument.Margins = new PdfMargins(100, 100, 100, 100);

// Add a new PDF page with the modified page settings
pdfDocument.AddPage();

Add PDF Elements to Document

After creating the document, you can start adding elements to it. The PdfDocument class provides dedicated methods such as PdfDocumentAddText(PdfTextElement) for adding a text element to the current page, and PdfDocumentAddImage(PdfImageElement) for adding an image element.

If the PDF page has margins set, they are automatically taken into account when rendering elements. Each element is positioned or resized accordingly to fit within the defined margins.

Save the PDF Document

After adding the desired elements to the PDF document, you can save the document to a file using the PdfDocumentSaveToFile(String) method. This method writes the PDF content to the specified file path on disk.

Save the PDF Document to a File
string outputPath = Path.Combine(outputDir, "GeneratedDocument.pdf");

// Save the document to disk
pdfDocument.SaveToFile(outputPath);

Alternatively, you can save the document to a memory buffer using the PdfDocumentSave overload without parameters, which returns a byte array.

Save the PDF Document to Memory
// Save the document to a memory buffer
byte[] pdfBytes = pdfDocument.Save();

There are also asynchronous variants of these methods that follow the Task-based Asynchronous Pattern (TAP) in .NET. These methods share the same names as their synchronous counterparts and include the "Async" suffix. They also accept an optional System.ThreadingCancellationToken parameter that can be used to cancel the operation where applicable.

You can asynchronously save the document to a file using the PdfDocumentSaveToFileAsync(String, CancellationToken) method. This method writes the PDF content to the specified file path on disk.

Asynchronously Save the PDF Document to a File
await pdfDocument.SaveToFileAsync(outputPath);

You can asynchronously save the document to a memory buffer using the PdfDocumentSaveAsync(CancellationToken) overload, which returns a byte array.

Asynchronously Save the PDF Document to Memory
byte[] pdfBytes = await pdfDocument.SaveAsync();

Dispose the PdfDocument

The Winnovative.Pdf.NextPdfDocument class implements IDisposable and should be disposed after use to release allocated resources.

Calling the PdfDocumentSave method will automatically dispose the document. After calling Save, the PdfDocument instance should no longer be used.

If you do not call Save, you must dispose the document manually either by using a using block or by calling Dispose explicitly.

Save and Dispose Automatically
// Save will dispose the document automatically
byte[] buffer = pdfDocument.Save();
Manual Dispose
PdfDocument pdfDocument = new PdfDocument();
byte[] buffer = pdfDocument.Save();
pdfDocument.Dispose();

Code Sample - Create PDF Documents with Text and Images

C#
using System.IO;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Winnovative_Next_AspNetDemo.Models;
using Winnovative_Next_AspNetDemo.Models.PDF_Creator;

// Use Winnovative Namespace
using Winnovative.Pdf.Next;

namespace Winnovative_Next_AspNetDemo.Controllers.PDF_Creator
{
    public class Create_PDF_DocumentsController : Controller
    {
        private readonly IWebHostEnvironment m_hostingEnvironment;

        public Create_PDF_DocumentsController(IWebHostEnvironment hostingEnvironment)
        {
            m_hostingEnvironment = hostingEnvironment;
        }

        public IActionResult Index()
        {
            var model = new Create_PDF_Documents_ViewModel();
            return View(model);
        }

        [HttpPost]
        public ActionResult CreatePdf(Create_PDF_Documents_ViewModel model)
        {
            if (!ModelState.IsValid)
            {
                var errorMessage = ModelStateHelper.GetModelErrors(ModelState);
                throw new ValidationException(errorMessage);
            }

            // Set license key received after purchase to use the library in licensed mode
            // Leave it not set to use the library in demo mode
            Licensing.LicenseKey = "3FJDU0ZDU0NTQkddQ1NAQl1CQV1KSkpKU0M=";

            PdfDocumentCreateSettings pdfCreateSettings = new PdfDocumentCreateSettings()
            {
                PageSize = PdfPageSize.A4,
                PageOrientation = PdfPageOrientation.Portrait,
                Margins = new PdfMargins(36, 36, 36, 36)
            };

            // Create a new PDF document with the specified settings
            using PdfDocument pdfDocument = new PdfDocument(pdfCreateSettings);

            const int startXPos = 0;
            const int startYPos = 0;
            const int ySeparator = 15;

            int currentPage = pdfDocument.PageNumber;
            int crtXPos = startXPos;
            int crtYPos = startYPos;

            // Create a standard Helvetica font
            PdfFont fontHelvetica = PdfFontManager.CreateStandardFont(PdfStandardFont.Helvetica, 16f,
                PdfFontStyle.Bold | PdfFontStyle.Underline, PdfColor.Black);

            // Add a title using the Helvetica font
            PdfTextElement pdfTitle1 = new PdfTextElement("Transparent PNG Image with Custom Width", fontHelvetica)
            {
                X = crtXPos,
                Y = crtYPos
            };
            PdfTextRenderInfo textRenderInfo = pdfDocument.AddText(pdfTitle1);

            // Update the Y position after rendering the title
            crtYPos = textRenderInfo.LastPageRectangle.Bounds.Bottom + ySeparator;

            string imagesPath = GetDemoImagesPath();

            // Add a transparent PNG image with custom width
            PdfImageElement pdfPngImage = new PdfImageElement(Path.Combine(imagesPath, "transparent.png"))
            {
                X = crtXPos,
                Y = crtYPos,
                Width = 150
            };
            PdfImageRenderInfo imageRenderInfo = pdfDocument.AddImage(pdfPngImage);

            crtYPos = imageRenderInfo.BoundingBox.Bottom + ySeparator;

            // Create a standard Courier font
            PdfFont fontCourier = PdfFontManager.CreateStandardFont(PdfStandardFont.Courier, 16f,
                PdfFontStyle.Bold | PdfFontStyle.Italic, PdfColor.Green);

            // Add a title for the JPEG image
            PdfTextElement pdfTitle2 = new PdfTextElement("JPEG Image with Custom Height", fontCourier)
            {
                X = crtXPos,
                Y = crtYPos
            };
            textRenderInfo = pdfDocument.AddText(pdfTitle2);

            crtYPos = textRenderInfo.LastPageRectangle.Bounds.Bottom + ySeparator;

            // Ensure there is enough vertical space on the current page for the image.
            // Add a new page and reset Y position if needed
            EnsureSpaceOnPage(ref crtYPos, 200, pdfDocument);

            // Add a JPEG image with custom height
            PdfImageElement pdfJpgImage = new PdfImageElement(Path.Combine(imagesPath, "image.jpg"))
            {
                X = crtXPos,
                Y = crtYPos,
                Height = 150
            };
            imageRenderInfo = pdfDocument.AddImage(pdfJpgImage);

            crtYPos = imageRenderInfo.BoundingBox.Bottom + ySeparator;

            string fontsPath = GetDemoFontsPath();
            string textsPath = GetDemoTextsPath();

            string alphabetFilePath = Path.Combine(textsPath, "Alphabet.txt");
            string alfabetString = System.IO.File.ReadAllText(alphabetFilePath);

            // Create a blue bold Courier font
            PdfFont fontCourier2 = PdfFontManager.CreateStandardFont(PdfStandardFont.Courier, 16f,
                PdfFontStyle.Bold, PdfColor.Blue);

            // Add a title for the Unicode text
            PdfTextElement pdfTitle3 = new PdfTextElement("Multi Page Unicode Text with Custom Font", fontCourier2)
            {
                Y = crtYPos,
                Alignment = PdfTextAlignment.Center
            };
            textRenderInfo = pdfDocument.AddText(pdfTitle3);

            crtYPos = textRenderInfo.LastPageRectangle.Bounds.Bottom + ySeparator;

            string dejaVuRegularFontFile = Path.Combine(fontsPath, "DejaVuSerif.ttf");

            // Create an Unicode TrueType font from file
            PdfFont trueTypeFont = PdfFontManager.CreateFont(dejaVuRegularFontFile, 16f,
                PdfFontStyle.Normal, PdfColor.Black);

            // Add long Unicode text using the TrueType font, allowing continuation on next pages
            PdfTextElement pdfText1 = new PdfTextElement(alfabetString, trueTypeFont)
            {
                X = crtXPos,
                Y = crtYPos,
                Alignment = PdfTextAlignment.Left,
                ContinueOnNextPage = true
            };

            // Draw a rectangle around rendered text in each page
            pdfText1.OnPageRendered = (pageNumber, boundingBox) =>
            {
                PdfRectangleElement border = new PdfRectangleElement(boundingBox.X, boundingBox.Y,
                    boundingBox.Width, boundingBox.Height + 5)
                {
                    BorderColor = PdfColor.Blue,
                };
                pdfDocument.AddRectangle(border);
            };

            textRenderInfo = pdfDocument.AddText(pdfText1);

            // Set the next page to landscape A4
            pdfDocument.SetPageSize(PdfPageSize.A4, PdfPageOrientation.Landscape);

            // Add a new page
            pdfDocument.AddPage();

            // Reset positions
            crtXPos = 0;
            crtYPos = 0;

            // Add the same text again, with the same font, centered
            PdfTextElement pdfText2 = new PdfTextElement(alfabetString, trueTypeFont)
            {
                X = crtXPos,
                Y = crtYPos,
                Alignment = PdfTextAlignment.Center,
                ContinueOnNextPage = true
            };

            pdfText2.OnPageRendered = (pageNumber, boundingBox) =>
            {
                PdfRectangleElement border = new PdfRectangleElement(boundingBox.X, boundingBox.Y,
                    boundingBox.Width, boundingBox.Height + 5)
                {
                    BorderColor = PdfColor.Purple,
                };
                pdfDocument.AddRectangle(border);
            };

            textRenderInfo = pdfDocument.AddText(pdfText2);

            // Add a new page
            pdfDocument.AddPage();

            // Reset positions
            crtXPos = 0;
            crtYPos = 0;

            PdfFont rtlTileFont = PdfFontManager.CreateStandardFont(PdfStandardFont.Courier, 16f, 
                PdfFontStyle.Normal, PdfColor.Purple);

            PdfTextElement rtlTitle = new PdfTextElement("Add Right to Left Text", rtlTileFont)
            {
                X = crtXPos,
                Y = crtYPos
            };
            textRenderInfo = pdfDocument.AddText(rtlTitle);
            crtYPos = textRenderInfo.LastPageRectangle.Bounds.Bottom + ySeparator;

            // Create a Unicode font that supports Arabic (RTL)
            string notoSansArabicRegularFontFile = Path.Combine(fontsPath, "NotoSansArabic-Regular.ttf");

            PdfFont trueTypeFontArabic = PdfFontManager.CreateFont(notoSansArabicRegularFontFile, 16f,
                PdfFontStyle.Normal, PdfColor.Black);

            string rtlFilePath = Path.Combine(textsPath, "RightToLeft.txt");
            string rtlString = System.IO.File.ReadAllText(rtlFilePath);

            // Render the right to left text
            PdfTextElement pdfTextRtl = new PdfTextElement(rtlString, trueTypeFontArabic)
            {
                X = crtXPos,
                Y = crtYPos,
                Direction = PdfTextDirection.RightToLeft
            };
            textRenderInfo = pdfDocument.AddText(pdfTextRtl);

            // Save to memory buffer
            byte[] outPdfBuffer = pdfDocument.Save();

            // Send PDF to browser
            FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");
            fileResult.FileDownloadName = "PdfDocument.pdf";

            return fileResult;
        }

        private void EnsureSpaceOnPage(ref int crtYPos, int requestedHeight, PdfDocument pdfDocument)
        {
            if (crtYPos + requestedHeight > pdfDocument.ContentHeight)
            {
                pdfDocument.AddPage();
                crtYPos = 0;
            }
        }

        private string GetDemoFilesPath()
        {
            return m_hostingEnvironment.ContentRootPath + "/wwwroot" + "/DemoAppFiles/Input/";
        }

        private string GetDemoImagesPath()
        {
            return Path.Combine(GetDemoFilesPath(), "Image_Files");
        }

        private string GetDemoFontsPath()
        {
            return Path.Combine(GetDemoFilesPath(), "Font_Files");
        }

        private string GetDemoTextsPath()
        {
            return Path.Combine(GetDemoFilesPath(), "Text_Files");
        }
    }
}

See Also