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.
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 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.
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);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 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.
// 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();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.
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.
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 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.
await pdfDocument.SaveToFileAsync(outputPath);You can asynchronously save the document to a memory buffer using the PdfDocumentSaveAsync(CancellationToken) overload, which returns a byte array.
byte[] pdfBytes = await pdfDocument.SaveAsync();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 will dispose the document automatically
byte[] buffer = pdfDocument.Save();PdfDocument pdfDocument = new PdfDocument();
byte[] buffer = pdfDocument.Save();
pdfDocument.Dispose();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 = "yUdWRldTRlZGVFZIVkZVV0hXVEhfX19fRlY=";
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");
}
}
}