SelectPdf for .NET 10 - Pdf Redaction - C# / .NET 10 Sample

This sample shows how to use SelectPdf Library for .NET to redact an existing PDF document. The text, images, links and form fields inside the redacted areas are removed from the document - not only covered - and each area is painted over with a fill color. Areas can be found by text or given as a rectangle on a page.

The sample uses the following (existing) test PDF, or a PDF you upload:
Test PDF document

PDF document (optional):

Redact text

Text to redact:


Match case
Whole words only

Or a regular expression (for example \b\d{3}-\d{2}-\d{4}\b):


Fill Color:


Overlay text (written in each area):


Password (for a protected PDF):


Redact an area (optional)
(Note: In points, from the top-left corner of the page. Leave the width empty to redact by text only.)

Page Number:


X:
pt

Y:
pt

Width:
pt

Height:
pt

Sample code · C#
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using SelectPdf.Universal;

namespace SelectPdf.Samples.Pages
{
    public class PdfRedactionModel : PageModel
    {
        public void OnGet()
        {
            TxtText = "SelectPdf";
            ChkWholeWords = true;
            DdlFillColor = "Black";
            TxtAreaPage = "1";
        }

        // An uploaded PDF document, or nothing - the shipped files/selectpdf.pdf is redacted then.
        [BindProperty]
        public IFormFile FilePdf { get; set; }

        [BindProperty]
        public string TxtText { get; set; }

        [BindProperty]
        public bool ChkCaseSensitive { get; set; }

        [BindProperty]
        public bool ChkWholeWords { get; set; }

        [BindProperty]
        public string TxtPattern { get; set; }

        [BindProperty]
        public string TxtOverlay { get; set; }

        [BindProperty]
        public string TxtPassword { get; set; }

        [BindProperty]
        public string DdlFillColor { get; set; }

        public List<SelectListItem> FillColors { get; } = new List<SelectListItem>
        {
            new SelectListItem { Value = "Black", Text = "Black" },
            new SelectListItem { Value = "Gray", Text = "Gray" },
            new SelectListItem { Value = "White", Text = "White" },
        };

        [BindProperty]
        public string TxtAreaPage { get; set; }

        [BindProperty]
        public string TxtAreaX { get; set; }

        [BindProperty]
        public string TxtAreaY { get; set; }

        [BindProperty]
        public string TxtAreaWidth { get; set; }

        [BindProperty]
        public string TxtAreaHeight { get; set; }

        public IActionResult OnPost()
        {
            // the document to redact: the uploaded one, or the test file
            byte[] source;
            if (FilePdf != null && FilePdf.Length > 0)
            {
                using (var uploaded = new MemoryStream())
                {
                    FilePdf.CopyTo(uploaded);
                    source = uploaded.ToArray();
                }
            }
            else
            {
                source = System.IO.File.ReadAllBytes(Path.Combine(Startup.ServerPath, "wwwroot", "files", "selectpdf.pdf"));
            }

            // load the document
            PdfRedactionManager manager = new PdfRedactionManager();
            if (string.IsNullOrEmpty(TxtPassword))
                manager.Load(source);
            else
                manager.Load(source, TxtPassword);

            // the color that covers the redacted areas
            switch (DdlFillColor)
            {
                case "Gray":
                    manager.FillColor = new PdfColor(128, 128, 128);
                    break;
                case "White":
                    manager.FillColor = new PdfColor(255, 255, 255);
                    break;
                default:
                    manager.FillColor = new PdfColor(0, 0, 0);
                    break;
            }

            // a text written in each redacted area
            if (!string.IsNullOrEmpty(TxtOverlay))
            {
                manager.OverlayText = TxtOverlay;
                // white on black and gray, black on white
                manager.OverlayTextColor = DdlFillColor == "White" ? new PdfColor(0, 0, 0) : new PdfColor(255, 255, 255);
            }

            // every occurrence of a text
            if (!string.IsNullOrEmpty(TxtText))
            {
                manager.AddRedaction(TxtText, ChkCaseSensitive, ChkWholeWords);
            }

            // every match of a regular expression
            if (!string.IsNullOrEmpty(TxtPattern))
            {
                manager.AddRedaction(new System.Text.RegularExpressions.Regex(TxtPattern,
                    ChkCaseSensitive ? System.Text.RegularExpressions.RegexOptions.None : System.Text.RegularExpressions.RegexOptions.IgnoreCase,
                    TimeSpan.FromSeconds(2)));
            }

            // a rectangle on a page
            if (TryNumber(TxtAreaWidth, out float width) && TryNumber(TxtAreaHeight, out float height)
                && width > 0 && height > 0)
            {
                TryNumber(TxtAreaX, out float x);
                TryNumber(TxtAreaY, out float y);
                int pageNumber = TryNumber(TxtAreaPage, out float page) ? (int)page : 1;
                manager.AddRedaction(pageNumber - 1, new SelectPdf.Universal.Drawing.RectangleF(x, y, width, height));
            }

            // apply the redaction and save the redacted document
            manager.Redact();
            byte[] pdf = manager.Save();

            // close the manager
            manager.Close();

            // return resulted pdf document
            FileResult fileResult = new FileContentResult(pdf, "application/pdf");
            fileResult.FileDownloadName = "Document.pdf";
            return fileResult;
        }

        private static bool TryNumber(string text, out float value)
        {
            return float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out value);
        }
    }
}