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 EvoPdf.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 EvoPdf.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 EvoPdf.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 EvoPdf_Next_AspNetDemo.Models;
using EvoPdf_Next_AspNetDemo.Models.PDF_Creator;

// Use EVO PDF Namespace
using EvoPdf.Next;

namespace EvoPdf_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 xLeft = 0;
            const int ySeparator = 15;
            int crtYPos = 0;

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

            // Each section title in this demo uses a different standard font so
            // the showcase exercises multiple font families/styles/colors in the
            // same document
            PdfFont fontHelveticaBoldUnderlineBlack = PdfFontManager.CreateStandardFont(
                PdfStandardFont.Helvetica, 16f, PdfFontStyle.Bold | PdfFontStyle.Underline, PdfColor.Black);
            PdfFont fontCourierBoldItalicGreen = PdfFontManager.CreateStandardFont(
                PdfStandardFont.Courier, 16f, PdfFontStyle.Bold | PdfFontStyle.Italic, PdfColor.Green);
            PdfFont fontCourierBoldBlue = PdfFontManager.CreateStandardFont(
                PdfStandardFont.Courier, 16f, PdfFontStyle.Bold, PdfColor.Blue);
            PdfFont fontCourierNormalPurple = PdfFontManager.CreateStandardFont(
                PdfStandardFont.Courier, 16f, PdfFontStyle.Normal, PdfColor.Purple);

            // ===== Section 1: Transparent PNG with custom width =====
            PdfTextElement pdfTitle1 = new PdfTextElement(
                "Transparent PNG Image with Custom Width", fontHelveticaBoldUnderlineBlack)
            {
                X = xLeft,
                Y = crtYPos
            };
            crtYPos = (int)pdfDocument.AddText(pdfTitle1).LastPageRectangle.Bounds.Bottom + ySeparator;

            PdfImageElement pdfPngImage = new PdfImageElement(Path.Combine(imagesPath, "transparent.png"))
            {
                X = xLeft,
                Y = crtYPos,
                Width = 150
            };
            crtYPos = (int)pdfDocument.AddImage(pdfPngImage).BoundingBox.Bottom + ySeparator;

            // ===== Section 2: JPEG with custom height =====
            PdfTextElement pdfTitle2 = new PdfTextElement(
                "JPEG Image with Custom Height", fontCourierBoldItalicGreen)
            {
                X = xLeft,
                Y = crtYPos
            };
            crtYPos = (int)pdfDocument.AddText(pdfTitle2).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);

            PdfImageElement pdfJpgImage = new PdfImageElement(Path.Combine(imagesPath, "image.jpg"))
            {
                X = xLeft,
                Y = crtYPos,
                Height = 150
            };
            crtYPos = (int)pdfDocument.AddImage(pdfJpgImage).BoundingBox.Bottom + ySeparator;

            // ===== Section 3: Multi-page Unicode text with per-page blue border =====
            PdfTextElement pdfTitle3 = new PdfTextElement(
                "Multi Page Unicode Text with Custom Font", fontCourierBoldBlue)
            {
                Y = crtYPos,
                Alignment = PdfTextAlignment.Center
            };
            crtYPos = (int)pdfDocument.AddText(pdfTitle3).LastPageRectangle.Bounds.Bottom + ySeparator;

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

            // Load the Unicode TrueType font used for the long alphabet body text
            string fontFilePath = Path.Combine(fontsPath, "DejaVuSerif.ttf");
            PdfBaseFont baseFont = PdfFontManager.CreateBaseFont(fontFilePath);
            PdfFont trueTypeFont = PdfFontManager.CreateFont(baseFont, 16f,
                PdfFontStyle.Normal, PdfColor.Black);

            // Long Unicode text using the TrueType font, allowing continuation on next pages.
            // The OnAfterPageRender callback draws a blue rectangle around the rendered area on
            // each page the text spans
            PdfTextElement pdfText1 = new PdfTextElement(alfabetString, trueTypeFont)
            {
                X = xLeft,
                Y = crtYPos,
                Alignment = PdfTextAlignment.Left,
                ContinueOnNextPage = true
            };

            pdfText1.OnAfterPageRender = info =>
            {
                var bounds = info.RenderedRectangle.Bounds;
                PdfRectangleElement border = new PdfRectangleElement(bounds.X, bounds.Y,
                    bounds.Width, bounds.Height + 5)
                {
                    BorderColor = PdfColor.Blue,
                };
                pdfDocument.AddRectangle(border);
            };

            pdfDocument.AddText(pdfText1);

            // ===== Section 4: Same text on landscape pages, centered, per-page purple border =====
            pdfDocument.SetPageSize(PdfPageSize.A4, PdfPageOrientation.Landscape);
            pdfDocument.AddPage();
            crtYPos = 0;

            PdfTextElement pdfText2 = new PdfTextElement(alfabetString, trueTypeFont)
            {
                X = xLeft,
                Y = crtYPos,
                Alignment = PdfTextAlignment.Center,
                ContinueOnNextPage = true
            };

            pdfText2.OnAfterPageRender = info =>
            {
                var bounds = info.RenderedRectangle.Bounds;
                PdfRectangleElement border = new PdfRectangleElement(bounds.X, bounds.Y,
                    bounds.Width, bounds.Height + 5)
                {
                    BorderColor = PdfColor.Purple,
                };
                pdfDocument.AddRectangle(border);
            };

            pdfDocument.AddText(pdfText2);

            // ===== Section 5: Right-to-left text =====
            pdfDocument.AddPage();
            crtYPos = 0;

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

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

            string rtlFontFilePath = Path.Combine(fontsPath, "NotoSansArabic-Regular.ttf");
            PdfFont rtlTrueTypeFont = PdfFontManager.CreateFont(rtlFontFilePath, 16f,
                PdfFontStyle.Normal, PdfColor.Black);

            PdfTextElement pdfTextRtl = new PdfTextElement(rtlString, rtlTrueTypeFont)
            {
                X = xLeft,
                Y = crtYPos,
                Direction = PdfTextDirection.RightToLeft
            };
            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