Redacción de PDF en C#;: Elimine datos confidenciales y desinfecte documentos con IronPDF

This article was translated from English: Does it need improvement?
Translated
View the article in English

Redacción de PDF en C# .NET con IronPDF elimina permanentemente el contenido sensible de la estructura interna de un documento, no sólo lo cubre visualmente, de modo que ninguna copia, búsqueda o análisis forense pueda recuperar los datos originales. Esto va mucho más allá de los rectángulos negros sobre el texto: IronPDF proporciona redacción de texto con concordancia de patrones regex, redacción basada en regiones para firmas e imágenes, eliminación de metadatos, desinfección de documentos para eliminar secuencias de comandos incrustadas y análisis de vulnerabilidades, lo que proporciona a los desarrolladores de .NET un conjunto de herramientas completo para flujos de trabajo de protección de documentos que cumplan con HIPAA, GDPR y PCI DSS.

TL;DR: Guía de inicio rápido

Este tutorial cubre la eliminación permanente de contenido sensible de documentos PDF en C# .NET, incluyendo patrones de texto, regiones de imagen, metadatos y scripts incrustados.

  • A quién va dirigido: Desarrolladores .NET que trabajan con documentos confidenciales en contextos sanitarios, jurídicos, financieros o gubernamentales.
  • Qué harás: Redacción de texto con concordancia de patrones regex (SSN, tarjetas de crédito, correos electrónicos), redacción de regiones basada en coordenadas para firmas y fotos, limpieza de metadatos, desinfección de PDF para eliminar scripts incrustados y escaneo de vulnerabilidades basado en YARA.
  • Dónde se ejecuta: .NET 10, .NET 8 LTS, .NET Framework 4.6.2+ y .NET Standard 2.0. Todas las operaciones se ejecutan localmente sin dependencias externas.
  • Cuándo utilizar este enfoque: Cuando necesite compartir documentos para descubrimiento legal, solicitudes FOIA o distribución externa mientras se asegura de que el contenido eliminado ha desaparecido realmente.
  • Por qué es importante desde el punto de vista técnico: Las superposiciones visuales dejan el texto original recuperable en los flujos de contenido del PDF. La redacción de IronPDF elimina los datos de caracteres de la propia estructura del documento, lo que hace imposible su recuperación.

Redacta texto sensible de un PDF con sólo unas pocas líneas de código:

Nuget IconEmpieza a crear PDF con NuGet ahora:

  1. Instalar IronPDF con el gestor de paquetes NuGet

    PM > Install-Package IronPdf

  2. Copie y ejecute este fragmento de código.

    using IronPdf;
    
    PdfDocument pdf = PdfDocument.FromFile("confidential-report.pdf");
    pdf.RedactTextOnAllPages("CONFIDENTIAL");
    pdf.SaveAs("redacted-report.pdf");
  3. Despliegue para probar en su entorno real

    Empieza a utilizar IronPDF en tu proyecto hoy mismo con una prueba gratuita
    arrow pointer

Una vez que haya adquirido IronPDF o se haya suscrito a una versión de prueba de 30 días, añada su clave de licencia al inicio de su solicitud.

IronPdf.License.LicenseKey = "KEY";
IronPdf.License.LicenseKey = "KEY";
Imports IronPdf

IronPdf.License.LicenseKey = "KEY"
$vbLabelText   $csharpLabel

Comience a usar IronPDF en su proyecto hoy con una prueba gratuita.

Primer Paso:
green arrow pointer
NuGet Instalar con NuGet

PM >  Install-Package IronPdf

Echa un vistazo a IronPDF en NuGet para una instalación rápida. Con más de 10 millones de descargas, está transformando el desarrollo de PDF con C#. También puede descargar el DLL o el instalador de Windows.

Índice

¿Cuál es la diferencia entre True Redaction y Visual Overlay?

Comprender la diferencia entre la verdadera redacción y la superposición visual es fundamental para cualquier persona que maneje documentos confidenciales. Muchas herramientas y métodos manuales crean la apariencia de redacción sin eliminar realmente los datos subyacentes. Esta falsa sensación de seguridad ha provocado numerosas filtraciones de datos y fallos en el cumplimiento de la normativa.

Los métodos de superposición visual suelen dibujar formas opacas sobre el contenido sensible. El texto debe permanecer intacto dentro de la estructura del PDF. Si alguien ve el documento, verá un rectángulo negro, pero los caracteres originales siguen existiendo en los flujos de contenido del archivo. La selección de todo el texto de la página, el uso de herramientas de accesibilidad o el examen de los datos en bruto del PDF revelarán todo lo que supuestamente estaba oculto. Los casos judiciales se han visto comprometidos cuando los archivos redactados han sido trivialmente omitidos por el abogado de la parte contraria. Las agencias gubernamentales han publicado accidentalmente información clasificada que parecía censurada pero que era completamente recuperable.

La verdadera redacción funciona de otra manera. Cuando se utilizan los métodos de redacción de IronPDF, la biblioteca localiza el texto especificado dentro de la estructura interna del PDF y lo elimina por completo. Los datos de caracteres se eliminan de los flujos de contenido. La representación visual se sustituye por una marca de redacción, normalmente un rectángulo negro, pero el contenido original ya no existe en ninguna parte del archivo. Ningún tipo de selección, copia o análisis forense puede recuperar lo que se ha borrado permanentemente.

IronPDF implementa la verdadera redacción modificando el PDF a nivel estructural. El método RedactTextOnAllPages y sus variantes buscan en el contenido de la página, identifican el texto coincidente, lo eliminan del modelo de objetos del documento y, opcionalmente, dibujan un indicador visual donde solía aparecer el contenido. Este enfoque se ajusta a las directrices de organizaciones como el NIST para la redacción segura de documentos.

Las implicaciones prácticas son significativas. Si necesita compartir documentos externamente, presentar archivos para su descubrimiento legal, publicar registros en virtud de solicitudes de libertad de información o distribuir informes protegiendo al mismo tiempo la información de identificación personal, sólo la redacción auténtica proporciona la protección adecuada. Las superposiciones visuales pueden ser suficientes para borradores internos en los que simplemente se quiere desviar la atención de ciertas secciones, pero nunca se debe confiar en ellas para la protección real de datos. Para conocer otras medidas de seguridad de los documentos, consulta nuestras guías sobre cifrado de PDF y firmas digitales.


¿Cómo Redactar Texto PDF en C# en Todo un Documento?

El escenario de redacción más común consiste en eliminar todas las instancias de un texto específico en un documento. Tal vez necesite eliminar el nombre de una persona de un informe, suprimir los números de cuenta de los estados financieros o eliminar los códigos de referencia internos antes de la distribución externa. IronPDF facilita esta tarea con el método RedactTextOnAllPages.

Entrada

Un documento de registro de empleados que contiene información personal como nombres, números de la Seguridad Social e identificaciones de empleados.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-text-all-pages.cs
using IronPdf;

// Load the source document
PdfDocument pdf = PdfDocument.FromFile("employee-records.pdf");

// Redact an employee name from the entire document
pdf.RedactTextOnAllPages("John Smith");

// Redact a Social Security Number
pdf.RedactTextOnAllPages("123-45-6789");

// Redact an internal employee ID
pdf.RedactTextOnAllPages("EMP-2024-0042");

// Save the cleaned document
pdf.SaveAs("employee-records-redacted.pdf");
Imports IronPdf

' Load the source document
Dim pdf As PdfDocument = PdfDocument.FromFile("employee-records.pdf")

' Redact an employee name from the entire document
pdf.RedactTextOnAllPages("John Smith")

' Redact a Social Security Number
pdf.RedactTextOnAllPages("123-45-6789")

' Redact an internal employee ID
pdf.RedactTextOnAllPages("EMP-2024-0042")

' Save the cleaned document
pdf.SaveAs("employee-records-redacted.pdf")
$vbLabelText   $csharpLabel

Este código carga un PDF que contiene información sobre los empleados y elimina tres datos confidenciales llamando a RedactTextOnAllPages para cada valor. Cada llamada busca en todas las páginas del documento y elimina permanentemente todas las instancias coincidentes del nombre, número de la Seguridad Social e identificador interno del empleado.

Muestra de resultado

El comportamiento predeterminado dibuja rectángulos negros donde aparecía el texto redactado y sustituye los caracteres reales por asteriscos en la estructura del documento. De este modo, se confirma visualmente que se ha producido una redacción y se garantiza que el contenido original ha desaparecido por completo.

Cuando se trabaja con documentos más largos o con varios objetivos de redacción, se pueden encadenar estas llamadas de forma eficaz:

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-text-list.cs
using IronPdf;
using System.Collections.Generic;

// Load the document once
PdfDocument pdf = PdfDocument.FromFile("quarterly-report.pdf");

// Define all terms that need redaction
List<string> sensitiveTerms = new List<string>
{
    "Project Titan",
    "Sarah Johnson",
    "Budget: $4.2M",
    "Q3-INTERNAL-2024",
    "sarah.johnson@company.com"
};

// Redact each term
foreach (string term in sensitiveTerms)
{
    pdf.RedactTextOnAllPages(term);
}

// Save the result
pdf.SaveAs("quarterly-report-public.pdf");
Imports IronPdf
Imports System.Collections.Generic

' Load the document once
Dim pdf As PdfDocument = PdfDocument.FromFile("quarterly-report.pdf")

' Define all terms that need redaction
Dim sensitiveTerms As New List(Of String) From {
    "Project Titan",
    "Sarah Johnson",
    "Budget: $4.2M",
    "Q3-INTERNAL-2024",
    "sarah.johnson@company.com"
}

' Redact each term
For Each term As String In sensitiveTerms
    pdf.RedactTextOnAllPages(term)
Next

' Save the result
pdf.SaveAs("quarterly-report-public.pdf")
$vbLabelText   $csharpLabel

Este patrón funciona bien cuando se tiene una lista conocida de valores sensibles que hay que eliminar. El documento se carga una vez, todas las redacciones se aplican en memoria y se guarda el resultado final. Cada término se procesa de forma independiente, por lo que las coincidencias parciales o las diferencias de formato entre términos no afectan a otras redacciones.

¿Cómo puedo redactar texto solo en determinadas páginas?

A veces se necesita un control más preciso sobre dónde se producen las redacciones. Un documento puede tener una portada con información que debe permanecer intacta, o puede saber que los datos confidenciales solo aparecen en determinadas secciones. IronPDF ofrece RedactTextOnPage para la redacción de una sola página y RedactTextOnPages para la redacción de varias páginas específicas.

Entrada

Un paquete de contratos de varias páginas con nombres de clientes en la página de la firma y términos financieros que aparecen en páginas específicas a lo largo del documento.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-specific-pages.cs
using IronPdf;

// Load the document
PdfDocument pdf = PdfDocument.FromFile("contract-bundle.pdf");

// Redact text only on page 1 (index 0)
pdf.RedactTextOnPage(0, "Client Name: Acme Corporation");

// Redact text on pages 3, 5, and 7 (indices 2, 4, 6)
int[] financialPages = { 2, 4, 6 };
pdf.RedactTextOnPages(financialPages, "Payment Terms: Net 30");

// Other pages remain untouched except for the specific redactions applied

pdf.SaveAs("contract-bundle-redacted.pdf");
Imports IronPdf

' Load the document
Dim pdf As PdfDocument = PdfDocument.FromFile("contract-bundle.pdf")

' Redact text only on page 1 (index 0)
pdf.RedactTextOnPage(0, "Client Name: Acme Corporation")

' Redact text on pages 3, 5, and 7 (indices 2, 4, 6)
Dim financialPages As Integer() = {2, 4, 6}
pdf.RedactTextOnPages(financialPages, "Payment Terms: Net 30")

' Other pages remain untouched except for the specific redactions applied

pdf.SaveAs("contract-bundle-redacted.pdf")
$vbLabelText   $csharpLabel

Este código demuestra la redacción selectiva utilizando RedactTextOnPage para una sola página y RedactTextOnPages para varias páginas específicas. El nombre del cliente se elimina únicamente de la página 1 (índice 0), mientras que las condiciones de pago se suprimen de las páginas 3, 5 y 7 (índices 2, 4 y 6), dejando el resto de páginas intactas.

Muestra de resultado

Los índices de página en IronPDF se basan en cero, lo que significa que la primera página es el índice 0, la segunda es el índice 1, y así sucesivamente. Esto coincide con las convenciones de programación estándar y se alinea con la forma en que la mayoría de los desarrolladores piensan sobre el acceso a matrices.

Dirigirse a páginas específicas mejora el rendimiento al procesar documentos de gran tamaño. En lugar de escanear cientos de páginas en busca de texto que solo aparece en unos pocos lugares, puede indicarle al motor de redacción exactamente dónde buscar. Esto es importante para los escenarios de procesamiento por lotes en los que se pueden manejar miles de documentos. Para obtener el máximo rendimiento, considere el uso de técnicas async y multithreading.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-large-document.cs
using IronPdf;

// Process a large document efficiently
PdfDocument pdf = PdfDocument.FromFile("annual-report-500-pages.pdf");

// We know from document structure that:
// - Executive summary with names is on pages 1-3
// - Financial data is on pages 45-60
// - Appendix with employee info is on pages 480-495

// Redact executive names from summary section
for (int i = 0; i <= 2; i++)
{
    pdf.RedactTextOnPage(i, "CEO: Robert Williams");
    pdf.RedactTextOnPage(i, "CFO: Maria Garcia");
}

// Redact specific financial figures from the financial section
int[] financialSection = { 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 };
pdf.RedactTextOnPages(financialSection, "Net Revenue: $847M");

// Redact employee identifiers from appendix
for (int i = 479; i <= 494; i++)
{
    pdf.RedactTextOnPage(i, "Employee ID:");
}

pdf.SaveAs("annual-report-public-release.pdf");
Imports IronPdf

' Process a large document efficiently
Dim pdf As PdfDocument = PdfDocument.FromFile("annual-report-500-pages.pdf")

' We know from document structure that:
' - Executive summary with names is on pages 1-3
' - Financial data is on pages 45-60
' - Appendix with employee info is on pages 480-495

' Redact executive names from summary section
For i As Integer = 0 To 2
    pdf.RedactTextOnPage(i, "CEO: Robert Williams")
    pdf.RedactTextOnPage(i, "CFO: Maria Garcia")
Next

' Redact specific financial figures from the financial section
Dim financialSection As Integer() = {44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}
pdf.RedactTextOnPages(financialSection, "Net Revenue: $847M")

' Redact employee identifiers from appendix
For i As Integer = 479 To 494
    pdf.RedactTextOnPage(i, "Employee ID:")
Next

pdf.SaveAs("annual-report-public-release.pdf")
$vbLabelText   $csharpLabel

Este enfoque específico procesa únicamente las secciones relevantes de un documento de 500 páginas, lo que reduce significativamente el tiempo de ejecución en comparación con el escaneo de cada página para cada término de redacción.

¿Cómo personalizo la apariencia del contenido redactado?

IronPDF ofrece varios parámetros para controlar cómo aparecen las redacciones en el documento final. Puede ajustar la distinción entre mayúsculas y minúsculas, la concordancia de palabras completas, si se deben dibujar rectángulos visuales y qué texto de sustitución aparece en lugar del contenido redactado.

Entrada

Un informe jurídico que contiene varios términos sensibles, como etiquetas de clasificación, contraseñas y códigos de referencia internos que requieren diferentes tratamientos de redacción.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/customize-redaction-appearance.cs
using IronPdf;

// Load the document
PdfDocument pdf = PdfDocument.FromFile("legal-brief.pdf");

// Case-sensitive redaction: only matches exact case
// "CLASSIFIED" will be redacted but "classified" or "Classified" will not
pdf.RedactTextOnAllPages(
    "CLASSIFIED",
    CaseSensitive: true,
    OnlyMatchWholeWords: true,
    DrawRectangles: true,
    ReplacementText: "[REDACTED]"
);

// Case-insensitive redaction: matches regardless of case
// Will redact "Secret", "SECRET", "secret", etc.
pdf.RedactTextOnAllPages(
    "secret",
    CaseSensitive: false,
    OnlyMatchWholeWords: true,
    DrawRectangles: true,
    ReplacementText: "*****"
);

// Whole word disabled: matches partial strings too
// Will redact "password", "passwords", "mypassword123", etc.
pdf.RedactTextOnAllPages(
    "password",
    CaseSensitive: false,
    OnlyMatchWholeWords: false,
    DrawRectangles: true,
    ReplacementText: "XXXXX"
);

// No visual rectangle: text is removed but no black box appears
// Useful when you want seamless removal without obvious redaction marks
pdf.RedactTextOnAllPages(
    "internal-reference-code",
    CaseSensitive: true,
    OnlyMatchWholeWords: true,
    DrawRectangles: false,
    ReplacementText: ""
);

pdf.SaveAs("legal-brief-redacted.pdf");
Imports IronPdf

' Load the document
Dim pdf As PdfDocument = PdfDocument.FromFile("legal-brief.pdf")

' Case-sensitive redaction: only matches exact case
' "CLASSIFIED" will be redacted but "classified" or "Classified" will not
pdf.RedactTextOnAllPages(
    "CLASSIFIED",
    CaseSensitive:=True,
    OnlyMatchWholeWords:=True,
    DrawRectangles:=True,
    ReplacementText:="[REDACTED]"
)

' Case-insensitive redaction: matches regardless of case
' Will redact "Secret", "SECRET", "secret", etc.
pdf.RedactTextOnAllPages(
    "secret",
    CaseSensitive:=False,
    OnlyMatchWholeWords:=True,
    DrawRectangles:=True,
    ReplacementText:="*****"
)

' Whole word disabled: matches partial strings too
' Will redact "password", "passwords", "mypassword123", etc.
pdf.RedactTextOnAllPages(
    "password",
    CaseSensitive:=False,
    OnlyMatchWholeWords:=False,
    DrawRectangles:=True,
    ReplacementText:="XXXXX"
)

' No visual rectangle: text is removed but no black box appears
' Useful when you want seamless removal without obvious redaction marks
pdf.RedactTextOnAllPages(
    "internal-reference-code",
    CaseSensitive:=True,
    OnlyMatchWholeWords:=True,
    DrawRectangles:=False,
    ReplacementText:=""
)

pdf.SaveAs("legal-brief-redacted.pdf")
$vbLabelText   $csharpLabel

Este código demuestra cuatro configuraciones de redacción diferentes utilizando los parámetros opcionales de RedactTextOnAllPages. Muestra la concordancia exacta entre mayúsculas y minúsculas con sustitución por "[REDACTED]", la concordancia entre mayúsculas y minúsculas con asteriscos, la concordancia parcial de palabras para captar variaciones como "contraseñas" y la eliminación invisible sin rectángulos visuales para eliminar contenido sin problemas.

Muestra de resultado

Los parámetros sirven para diferentes propósitos dependiendo de sus requisitos:

CaseSensitive determina si la concordancia tiene en cuenta las mayúsculas y minúsculas. Los documentos jurídicos suelen utilizar mayúsculas y minúsculas específicas que conllevan un significado, por lo que la concordancia entre mayúsculas y minúsculas garantiza que solo se eliminen las coincidencias exactas. El procesamiento de texto general en el que las mayúsculas y minúsculas varían puede requerir una concordancia que no distinga entre mayúsculas y minúsculas para detectar todos los casos.

OnlyMatchWholeWords controla si la búsqueda busca palabras completas o cadenas parciales. A la hora de redactar nombres, normalmente se busca la concordancia de la palabra completa para que "Smith" no redacte accidentalmente parte de "Blacksmith" o "Smithfield". Al redactar patrones como prefijos de números de cuenta, puede ser necesaria una concordancia parcial para detectar variaciones.

DrawRectangles especifica si aparecen cuadros negros donde se ha eliminado contenido. La mayoría de los contextos normativos y jurídicos exigen marcas de redacción visibles como prueba de que el contenido se eliminó deliberadamente en lugar de omitirse accidentalmente. Los flujos de trabajo internos pueden preferir la eliminación invisible para obtener un resultado más limpio.

Texto de sustitución define qué caracteres aparecen en lugar del contenido redactado. Las opciones más comunes incluyen asteriscos, etiquetas "REDACTED" o cadenas vacías. El texto de sustitución aparece en la estructura del documento si alguien intenta seleccionar o copiar desde el área redactada.


¿Cómo puedo usar expresiones regulares para encontrar y censurar patrones sensibles?

Redactar cadenas de texto conocidas funciona cuando se tienen valores específicos que eliminar, pero muchos tipos de datos confidenciales siguen patrones predecibles en lugar de valores fijos. Los números de la Seguridad Social, los números de tarjetas de crédito, las direcciones de correo electrónico, los números de teléfono y las fechas tienen formatos reconocibles que pueden compararse con expresiones regulares. La creación de un sistema de redacción basado en patrones permite eliminar información privada del contenido de un PDF sin conocer de antemano cada valor específico.

Las capacidades de extracción de texto de IronPDF, combinadas con métodos de redacción, permiten potentes flujos de trabajo de concordancia de patrones. Usted extrae el texto, identifica las coincidencias utilizando expresiones regulares .NET y, a continuación, redacta cada valor descubierto.

using IronPdf;
using System.Text.RegularExpressions;
using System.Collections.Generic;

public class PatternRedactor
{
    // Common patterns for sensitive data
    private static readonly Dictionary<string, string> SensitivePatterns = new Dictionary<string, string>
    {
        // US Social Security Number: 123-45-6789
        { "SSN", @"\b\d{3}-\d{2}-\d{4}\b" },

        // Credit Card Numbers: various formats with 13-19 digits
        { "CreditCard", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },

        // Email Addresses
        { "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },

        // US Phone Numbers: (123) 456-7890 or 123-456-7890
        { "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" },

        // Dates: MM/DD/YYYY or MM-DD-YYYY
        { "Date", @"\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" },

        // IP Addresses
        { "IPAddress", @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b" }
    };

    public void RedactPatterns(string inputPath, string outputPath, params string[] patternNames)
    {
        // Load the PDF
        PdfDocument pdf = PdfDocument.FromFile(inputPath);

        // Extract all text from the document
        string fullText = pdf.ExtractAllText();

        // Track unique matches to avoid duplicate redaction attempts
        HashSet<string> matchesToRedact = new HashSet<string>();

        // Find all matches for requested patterns
        foreach (string patternName in patternNames)
        {
            if (SensitivePatterns.TryGetValue(patternName, out string pattern))
            {
                Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
                MatchCollection matches = regex.Matches(fullText);

                foreach (Match match in matches)
                {
                    matchesToRedact.Add(match.Value);
                }
            }
        }

        // Redact each unique match
        foreach (string sensitiveValue in matchesToRedact)
        {
            pdf.RedactTextOnAllPages(sensitiveValue);
        }

        // Save the redacted document
        pdf.SaveAs(outputPath);
    }
}

// Usage example
class Program
{
    static void Main()
    {
        PatternRedactor redactor = new PatternRedactor();

        // Redact SSNs and credit cards from a financial document
        redactor.RedactPatterns(
            "customer-data.pdf",
            "customer-data-safe.pdf",
            "SSN", "CreditCard", "Email"
        );
    }
}
using IronPdf;
using System.Text.RegularExpressions;
using System.Collections.Generic;

public class PatternRedactor
{
    // Common patterns for sensitive data
    private static readonly Dictionary<string, string> SensitivePatterns = new Dictionary<string, string>
    {
        // US Social Security Number: 123-45-6789
        { "SSN", @"\b\d{3}-\d{2}-\d{4}\b" },

        // Credit Card Numbers: various formats with 13-19 digits
        { "CreditCard", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },

        // Email Addresses
        { "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },

        // US Phone Numbers: (123) 456-7890 or 123-456-7890
        { "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" },

        // Dates: MM/DD/YYYY or MM-DD-YYYY
        { "Date", @"\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" },

        // IP Addresses
        { "IPAddress", @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b" }
    };

    public void RedactPatterns(string inputPath, string outputPath, params string[] patternNames)
    {
        // Load the PDF
        PdfDocument pdf = PdfDocument.FromFile(inputPath);

        // Extract all text from the document
        string fullText = pdf.ExtractAllText();

        // Track unique matches to avoid duplicate redaction attempts
        HashSet<string> matchesToRedact = new HashSet<string>();

        // Find all matches for requested patterns
        foreach (string patternName in patternNames)
        {
            if (SensitivePatterns.TryGetValue(patternName, out string pattern))
            {
                Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
                MatchCollection matches = regex.Matches(fullText);

                foreach (Match match in matches)
                {
                    matchesToRedact.Add(match.Value);
                }
            }
        }

        // Redact each unique match
        foreach (string sensitiveValue in matchesToRedact)
        {
            pdf.RedactTextOnAllPages(sensitiveValue);
        }

        // Save the redacted document
        pdf.SaveAs(outputPath);
    }
}

// Usage example
class Program
{
    static void Main()
    {
        PatternRedactor redactor = new PatternRedactor();

        // Redact SSNs and credit cards from a financial document
        redactor.RedactPatterns(
            "customer-data.pdf",
            "customer-data-safe.pdf",
            "SSN", "CreditCard", "Email"
        );
    }
}
Imports IronPdf
Imports System.Text.RegularExpressions
Imports System.Collections.Generic

Public Class PatternRedactor
    ' Common patterns for sensitive data
    Private Shared ReadOnly SensitivePatterns As New Dictionary(Of String, String) From {
        ' US Social Security Number: 123-45-6789
        {"SSN", "\b\d{3}-\d{2}-\d{4}\b"},

        ' Credit Card Numbers: various formats with 13-19 digits
        {"CreditCard", "\b(?:\d{4}[-\s]?){3}\d{1,4}\b"},

        ' Email Addresses
        {"Email", "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"},

        ' US Phone Numbers: (123) 456-7890 or 123-456-7890
        {"Phone", "\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b"},

        ' Dates: MM/DD/YYYY or MM-DD-YYYY
        {"Date", "\b\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b"},

        ' IP Addresses
        {"IPAddress", "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"}
    }

    Public Sub RedactPatterns(inputPath As String, outputPath As String, ParamArray patternNames As String())
        ' Load the PDF
        Dim pdf As PdfDocument = PdfDocument.FromFile(inputPath)

        ' Extract all text from the document
        Dim fullText As String = pdf.ExtractAllText()

        ' Track unique matches to avoid duplicate redaction attempts
        Dim matchesToRedact As New HashSet(Of String)()

        ' Find all matches for requested patterns
        For Each patternName As String In patternNames
            Dim pattern As String = Nothing
            If SensitivePatterns.TryGetValue(patternName, pattern) Then
                Dim regex As New Regex(pattern, RegexOptions.IgnoreCase)
                Dim matches As MatchCollection = regex.Matches(fullText)

                For Each match As Match In matches
                    matchesToRedact.Add(match.Value)
                Next
            End If
        Next

        ' Redact each unique match
        For Each sensitiveValue As String In matchesToRedact
            pdf.RedactTextOnAllPages(sensitiveValue)
        Next

        ' Save the redacted document
        pdf.SaveAs(outputPath)
    End Sub
End Class

' Usage example
Class Program
    Shared Sub Main()
        Dim redactor As New PatternRedactor()

        ' Redact SSNs and credit cards from a financial document
        redactor.RedactPatterns(
            "customer-data.pdf",
            "customer-data-safe.pdf",
            "SSN", "CreditCard", "Email"
        )
    End Sub
End Class
$vbLabelText   $csharpLabel

Este enfoque basado en patrones se adapta bien porque los patrones se definen una vez y se aplican a cualquier documento. La adición de nuevos tipos de datos sólo requiere añadir nuevos patrones regex al diccionario.

¿Cómo construir un escáner de datos sensibles reutilizable?

En los entornos de producción, a menudo es necesario escanear los documentos e informar de qué información confidencial existe antes de decidir si se redacta o no. Esto ayuda en la auditoría de cumplimiento y permite la revisión humana de las decisiones de redacción. La siguiente clase ofrece funciones de escaneado junto con la redacción.

using IronPdf;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Linq;

public class SensitiveDataMatch
{
    public string PatternType { get; set; }
    public string Value { get; set; }
    public int PageNumber { get; set; }
}

public class ScanResult
{
    public string FilePath { get; set; }
    public List<SensitiveDataMatch> Matches { get; set; } = new List<SensitiveDataMatch>();
    public bool ContainsSensitiveData => Matches.Count > 0;

    public Dictionary<string, int> GetSummary()
    {
        return Matches.GroupBy(m => m.PatternType)
                      .ToDictionary(g => g.Key, g => g.Count());
    }
}

public class DocumentScanner
{
    private readonly Dictionary<string, string> _patterns;

    public DocumentScanner()
    {
        _patterns = new Dictionary<string, string>
        {
            { "Social Security Number", @"\b\d{3}-\d{2}-\d{4}\b" },
            { "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
            { "Email Address", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
            { "Phone Number", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" },
            { "Date of Birth Pattern", @"\b(?:DOB|Date of Birth|Birth Date)[:\s]+\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" }
        };
    }

    public ScanResult ScanDocument(string filePath)
    {
        ScanResult result = new ScanResult { FilePath = filePath };
        PdfDocument pdf = PdfDocument.FromFile(filePath);

        // Scan each page individually to track location
        for (int pageIndex = 0; pageIndex < pdf.PageCount; pageIndex++)
        {
            string pageText = pdf.ExtractTextFromPage(pageIndex);

            foreach (var pattern in _patterns)
            {
                Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
                MatchCollection matches = regex.Matches(pageText);

                foreach (Match match in matches)
                {
                    result.Matches.Add(new SensitiveDataMatch
                    {
                        PatternType = pattern.Key,
                        Value = MaskValue(match.Value, pattern.Key),
                        PageNumber = pageIndex + 1
                    });
                }
            }
        }

        return result;
    }

    // Partially mask values for safe storage
    private string MaskValue(string value, string patternType)
    {
        if (patternType == "Social Security Number" && value.Length >= 4)
        {
            return "XXX-XX-" + value.Substring(value.Length - 4);
        }
        if (patternType == "Credit Card" && value.Length >= 4)
        {
            return "****-****-****-" + value.Substring(value.Length - 4);
        }
        if (patternType == "Email Address")
        {
            int atIndex = value.IndexOf('@');
            if (atIndex > 2)
            {
                return value.Substring(0, 2) + "***" + value.Substring(atIndex);
            }
        }
        return value.Length > 4 ? value.Substring(0, 2) + "***" : "****";
    }

    public void ScanAndRedact(string inputPath, string outputPath)
    {
        // First scan to identify sensitive data
        ScanResult scanResult = ScanDocument(inputPath);

        if (!scanResult.ContainsSensitiveData)
        {
            return;
        }

        // Load document for redaction
        PdfDocument pdf = PdfDocument.FromFile(inputPath);

        // Extract unique actual values (not masked) for redaction
        string fullText = pdf.ExtractAllText();
        HashSet<string> valuesToRedact = new HashSet<string>();

        foreach (var pattern in _patterns)
        {
            Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
            foreach (Match match in regex.Matches(fullText))
            {
                valuesToRedact.Add(match.Value);
            }
        }

        // Apply redactions
        foreach (string value in valuesToRedact)
        {
            pdf.RedactTextOnAllPages(value);
        }

        pdf.SaveAs(outputPath);
    }
}

// Usage
class Program
{
    static void Main()
    {
        DocumentScanner scanner = new DocumentScanner();

        // Scan only (for audit purposes)
        ScanResult result = scanner.ScanDocument("application-form.pdf");
        var summary = result.GetSummary();

        // Scan and redact in one operation
        scanner.ScanAndRedact("application-form.pdf", "application-form-redacted.pdf");
    }
}
using IronPdf;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Linq;

public class SensitiveDataMatch
{
    public string PatternType { get; set; }
    public string Value { get; set; }
    public int PageNumber { get; set; }
}

public class ScanResult
{
    public string FilePath { get; set; }
    public List<SensitiveDataMatch> Matches { get; set; } = new List<SensitiveDataMatch>();
    public bool ContainsSensitiveData => Matches.Count > 0;

    public Dictionary<string, int> GetSummary()
    {
        return Matches.GroupBy(m => m.PatternType)
                      .ToDictionary(g => g.Key, g => g.Count());
    }
}

public class DocumentScanner
{
    private readonly Dictionary<string, string> _patterns;

    public DocumentScanner()
    {
        _patterns = new Dictionary<string, string>
        {
            { "Social Security Number", @"\b\d{3}-\d{2}-\d{4}\b" },
            { "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
            { "Email Address", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
            { "Phone Number", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" },
            { "Date of Birth Pattern", @"\b(?:DOB|Date of Birth|Birth Date)[:\s]+\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b" }
        };
    }

    public ScanResult ScanDocument(string filePath)
    {
        ScanResult result = new ScanResult { FilePath = filePath };
        PdfDocument pdf = PdfDocument.FromFile(filePath);

        // Scan each page individually to track location
        for (int pageIndex = 0; pageIndex < pdf.PageCount; pageIndex++)
        {
            string pageText = pdf.ExtractTextFromPage(pageIndex);

            foreach (var pattern in _patterns)
            {
                Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
                MatchCollection matches = regex.Matches(pageText);

                foreach (Match match in matches)
                {
                    result.Matches.Add(new SensitiveDataMatch
                    {
                        PatternType = pattern.Key,
                        Value = MaskValue(match.Value, pattern.Key),
                        PageNumber = pageIndex + 1
                    });
                }
            }
        }

        return result;
    }

    // Partially mask values for safe storage
    private string MaskValue(string value, string patternType)
    {
        if (patternType == "Social Security Number" && value.Length >= 4)
        {
            return "XXX-XX-" + value.Substring(value.Length - 4);
        }
        if (patternType == "Credit Card" && value.Length >= 4)
        {
            return "****-****-****-" + value.Substring(value.Length - 4);
        }
        if (patternType == "Email Address")
        {
            int atIndex = value.IndexOf('@');
            if (atIndex > 2)
            {
                return value.Substring(0, 2) + "***" + value.Substring(atIndex);
            }
        }
        return value.Length > 4 ? value.Substring(0, 2) + "***" : "****";
    }

    public void ScanAndRedact(string inputPath, string outputPath)
    {
        // First scan to identify sensitive data
        ScanResult scanResult = ScanDocument(inputPath);

        if (!scanResult.ContainsSensitiveData)
        {
            return;
        }

        // Load document for redaction
        PdfDocument pdf = PdfDocument.FromFile(inputPath);

        // Extract unique actual values (not masked) for redaction
        string fullText = pdf.ExtractAllText();
        HashSet<string> valuesToRedact = new HashSet<string>();

        foreach (var pattern in _patterns)
        {
            Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
            foreach (Match match in regex.Matches(fullText))
            {
                valuesToRedact.Add(match.Value);
            }
        }

        // Apply redactions
        foreach (string value in valuesToRedact)
        {
            pdf.RedactTextOnAllPages(value);
        }

        pdf.SaveAs(outputPath);
    }
}

// Usage
class Program
{
    static void Main()
    {
        DocumentScanner scanner = new DocumentScanner();

        // Scan only (for audit purposes)
        ScanResult result = scanner.ScanDocument("application-form.pdf");
        var summary = result.GetSummary();

        // Scan and redact in one operation
        scanner.ScanAndRedact("application-form.pdf", "application-form-redacted.pdf");
    }
}
Imports IronPdf
Imports System.Collections.Generic
Imports System.Text.RegularExpressions
Imports System.Linq

Public Class SensitiveDataMatch
    Public Property PatternType As String
    Public Property Value As String
    Public Property PageNumber As Integer
End Class

Public Class ScanResult
    Public Property FilePath As String
    Public Property Matches As List(Of SensitiveDataMatch) = New List(Of SensitiveDataMatch)()
    Public ReadOnly Property ContainsSensitiveData As Boolean
        Get
            Return Matches.Count > 0
        End Get
    End Property

    Public Function GetSummary() As Dictionary(Of String, Integer)
        Return Matches.GroupBy(Function(m) m.PatternType) _
                      .ToDictionary(Function(g) g.Key, Function(g) g.Count())
    End Function
End Class

Public Class DocumentScanner
    Private ReadOnly _patterns As Dictionary(Of String, String)

    Public Sub New()
        _patterns = New Dictionary(Of String, String) From {
            {"Social Security Number", "\b\d{3}-\d{2}-\d{4}\b"},
            {"Credit Card", "\b(?:\d{4}[-\s]?){3}\d{1,4}\b"},
            {"Email Address", "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"},
            {"Phone Number", "\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b"},
            {"Date of Birth Pattern", "\b(?:DOB|Date of Birth|Birth Date)[:\s]+\d{1,2}[/-]\d{1,2}[/-]\d{2,4}\b"}
        }
    End Sub

    Public Function ScanDocument(filePath As String) As ScanResult
        Dim result As New ScanResult With {.FilePath = filePath}
        Dim pdf As PdfDocument = PdfDocument.FromFile(filePath)

        ' Scan each page individually to track location
        For pageIndex As Integer = 0 To pdf.PageCount - 1
            Dim pageText As String = pdf.ExtractTextFromPage(pageIndex)

            For Each pattern In _patterns
                Dim regex As New Regex(pattern.Value, RegexOptions.IgnoreCase)
                Dim matches As MatchCollection = regex.Matches(pageText)

                For Each match As Match In matches
                    result.Matches.Add(New SensitiveDataMatch With {
                        .PatternType = pattern.Key,
                        .Value = MaskValue(match.Value, pattern.Key),
                        .PageNumber = pageIndex + 1
                    })
                Next
            Next
        Next

        Return result
    End Function

    ' Partially mask values for safe storage
    Private Function MaskValue(value As String, patternType As String) As String
        If patternType = "Social Security Number" AndAlso value.Length >= 4 Then
            Return "XXX-XX-" & value.Substring(value.Length - 4)
        End If
        If patternType = "Credit Card" AndAlso value.Length >= 4 Then
            Return "****-****-****-" & value.Substring(value.Length - 4)
        End If
        If patternType = "Email Address" Then
            Dim atIndex As Integer = value.IndexOf("@"c)
            If atIndex > 2 Then
                Return value.Substring(0, 2) & "***" & value.Substring(atIndex)
            End If
        End If
        Return If(value.Length > 4, value.Substring(0, 2) & "***", "****")
    End Function

    Public Sub ScanAndRedact(inputPath As String, outputPath As String)
        ' First scan to identify sensitive data
        Dim scanResult As ScanResult = ScanDocument(inputPath)

        If Not scanResult.ContainsSensitiveData Then
            Return
        End If

        ' Load document for redaction
        Dim pdf As PdfDocument = PdfDocument.FromFile(inputPath)

        ' Extract unique actual values (not masked) for redaction
        Dim fullText As String = pdf.ExtractAllText()
        Dim valuesToRedact As New HashSet(Of String)()

        For Each pattern In _patterns
            Dim regex As New Regex(pattern.Value, RegexOptions.IgnoreCase)
            For Each match As Match In regex.Matches(fullText)
                valuesToRedact.Add(match.Value)
            Next
        Next

        ' Apply redactions
        For Each value As String In valuesToRedact
            pdf.RedactTextOnAllPages(value)
        Next

        pdf.SaveAs(outputPath)
    End Sub
End Class

' Usage
Module Program
    Sub Main()
        Dim scanner As New DocumentScanner()

        ' Scan only (for audit purposes)
        Dim result As ScanResult = scanner.ScanDocument("application-form.pdf")
        Dim summary = result.GetSummary()

        ' Scan and redact in one operation
        scanner.ScanAndRedact("application-form.pdf", "application-form-redacted.pdf")
    End Sub
End Module
$vbLabelText   $csharpLabel

El escáner ofrece visibilidad sobre la información confidencial existente antes de que se produzca cualquier modificación. Esto respalda los flujos de trabajo de conformidad en los que se necesita documentación sobre lo que se ha encontrado y eliminado. La función de enmascaramiento garantiza que los archivos de registro y los informes no se conviertan en fuentes de exposición de datos.


¿Cómo redacto regiones o áreas específicas de un PDF?

La redacción de texto gestiona eficazmente el contenido basado en caracteres, pero los PDF suelen contener información sensible en formas que la concordancia de texto no puede abordar. Las firmas, fotografías, anotaciones manuscritas, sellos y elementos gráficos requieren un enfoque diferente. La redacción basada en regiones permite especificar áreas rectangulares por sus coordenadas y oscurecer permanentemente todo lo que se encuentre dentro de esos límites.

IronPDF utiliza la estructura RectangleF para definir las regiones de redacción. Especifique las coordenadas X e Y de la esquina superior izquierda y, a continuación, la anchura y la altura del área. Las coordenadas se miden en puntos desde la parte inferior izquierda de la página, lo que coincide con el sistema de coordenadas de la especificación PDF.

Entrada

Un documento de acuerdo firmado que contiene firmas manuscritas y un documento de identidad con fotografía que deben redactarse utilizando la orientación por regiones basada en coordenadas.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-region-basic.cs
using IronPdf;
using IronSoftware.Drawing;

// Load a document with signature blocks and photos
PdfDocument pdf = PdfDocument.FromFile("signed-agreement.pdf");

// Define a region for a signature block
// Located 100 points from left, 650 points from bottom
// Width of 200 points, height of 50 points
RectangleF signatureRegion = new RectangleF(100, 650, 200, 50);

// Redact the signature region on all pages
pdf.RedactRegionsOnAllPages(signatureRegion);

// Define a region for a photo ID in the upper right
RectangleF photoRegion = new RectangleF(450, 700, 100, 120);
pdf.RedactRegionsOnAllPages(photoRegion);

// Save the document with regions redacted
pdf.SaveAs("signed-agreement-redacted.pdf");
Imports IronPdf
Imports IronSoftware.Drawing

' Load a document with signature blocks and photos
Dim pdf As PdfDocument = PdfDocument.FromFile("signed-agreement.pdf")

' Define a region for a signature block
' Located 100 points from left, 650 points from bottom
' Width of 200 points, height of 50 points
Dim signatureRegion As New RectangleF(100, 650, 200, 50)

' Redact the signature region on all pages
pdf.RedactRegionsOnAllPages(signatureRegion)

' Define a region for a photo ID in the upper right
Dim photoRegion As New RectangleF(450, 700, 100, 120)
pdf.RedactRegionsOnAllPages(photoRegion)

' Save the document with regions redacted
pdf.SaveAs("signed-agreement-redacted.pdf")
$vbLabelText   $csharpLabel

Este código utiliza estructuras RectangleF para definir áreas rectangulares para la redacción. La región de la firma se sitúa en las coordenadas (100, 650) con un área de 200x50 píxeles, mientras que la región de la foto se sitúa en (450, 700) con un área de 100x120 píxeles. El método RedactRegionsOnAllPages aplica rectángulos negros sobre estas regiones en todas las páginas.

Muestra de resultado

Determinar las coordenadas correctas suele requerir cierta experimentación o medición. Las páginas PDF suelen utilizar un sistema de coordenadas en el que un punto equivale a 1/72 de pulgada. Una página US Letter estándar tiene 612 puntos de ancho y 792 puntos de alto. Las páginas A4 miden aproximadamente 595 por 842 puntos. Las herramientas de visualización de PDF que muestran las coordenadas al mover el cursor pueden ayudar, o se pueden extraer las dimensiones de la página mediante programación:

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-region-dimensions.cs
using IronPdf;
using IronSoftware.Drawing;

PdfDocument pdf = PdfDocument.FromFile("form-document.pdf");

// Get dimensions of the first page
var pageInfo = pdf.Pages[0];

// Calculate regions relative to page dimensions
// Redact the bottom quarter of the page where signatures appear
float signatureAreaHeight = (float)(pageInfo.Height / 4);
RectangleF bottomQuarter = new RectangleF(
    0,                              // Start at left edge
    0,                              // Start at bottom
    (float)pageInfo.Width,          // Full page width
    signatureAreaHeight             // Quarter of page height
);

pdf.RedactRegionsOnAllPages(bottomQuarter);

// Redact a header area at the top containing letterhead with address
float headerHeight = 100;
RectangleF headerArea = new RectangleF(
    0,
    (float)(pageInfo.Height - headerHeight), // Position from bottom
    (float)pageInfo.Width,
    headerHeight
);

pdf.RedactRegionsOnAllPages(headerArea);

pdf.SaveAs("form-document-redacted.pdf");
Imports IronPdf
Imports IronSoftware.Drawing

Dim pdf As PdfDocument = PdfDocument.FromFile("form-document.pdf")

' Get dimensions of the first page
Dim pageInfo = pdf.Pages(0)

' Calculate regions relative to page dimensions
' Redact the bottom quarter of the page where signatures appear
Dim signatureAreaHeight As Single = CSng(pageInfo.Height / 4)
Dim bottomQuarter As New RectangleF(0, 0, CSng(pageInfo.Width), signatureAreaHeight)

pdf.RedactRegionsOnAllPages(bottomQuarter)

' Redact a header area at the top containing letterhead with address
Dim headerHeight As Single = 100
Dim headerArea As New RectangleF(0, CSng(pageInfo.Height - headerHeight), CSng(pageInfo.Width), headerHeight)

pdf.RedactRegionsOnAllPages(headerArea)

pdf.SaveAs("form-document-redacted.pdf")
$vbLabelText   $csharpLabel

¿Cómo puedo redactar varias regiones en distintas páginas?

Los documentos complejos suelen requerir que se redacten diferentes regiones en distintas páginas. Un formulario de varias páginas puede tener líneas de firma en distintas posiciones, o diferentes páginas pueden contener fotos, sellos u otros elementos gráficos en ubicaciones únicas. IronPDF incluye métodos específicos de página para la redacción de regiones específicas.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/redact-multiple-regions.cs
using IronPdf;
using IronSoftware.Drawing;

PdfDocument pdf = PdfDocument.FromFile("multi-page-application.pdf");

// Define page-specific redaction regions
// Page 1: Cover page with applicant photo
RectangleF page1Photo = new RectangleF(450, 600, 120, 150);
pdf.RedactRegionOnPage(0, page1Photo);

// Page 2: Personal information section
RectangleF page2InfoBlock = new RectangleF(50, 400, 250, 200);
pdf.RedactRegionOnPage(1, page2InfoBlock);

// Pages 3-5: Signature lines at the same position
RectangleF signatureLine = new RectangleF(100, 100, 200, 40);
int[] signaturePages = { 2, 3, 4 };
pdf.RedactRegionOnPages(signaturePages, signatureLine);

// Page 6: Multiple regions - notary stamp and witness signature
RectangleF notaryStamp = new RectangleF(400, 150, 150, 150);
RectangleF witnessSignature = new RectangleF(100, 150, 200, 40);
pdf.RedactRegionOnPage(5, notaryStamp);
pdf.RedactRegionOnPage(5, witnessSignature);

pdf.SaveAs("multi-page-application-redacted.pdf");
Imports IronPdf
Imports IronSoftware.Drawing

Dim pdf As PdfDocument = PdfDocument.FromFile("multi-page-application.pdf")

' Define page-specific redaction regions
' Page 1: Cover page with applicant photo
Dim page1Photo As New RectangleF(450, 600, 120, 150)
pdf.RedactRegionOnPage(0, page1Photo)

' Page 2: Personal information section
Dim page2InfoBlock As New RectangleF(50, 400, 250, 200)
pdf.RedactRegionOnPage(1, page2InfoBlock)

' Pages 3-5: Signature lines at the same position
Dim signatureLine As New RectangleF(100, 100, 200, 40)
Dim signaturePages As Integer() = {2, 3, 4}
pdf.RedactRegionOnPages(signaturePages, signatureLine)

' Page 6: Multiple regions - notary stamp and witness signature
Dim notaryStamp As New RectangleF(400, 150, 150, 150)
Dim witnessSignature As New RectangleF(100, 150, 200, 40)
pdf.RedactRegionOnPage(5, notaryStamp)
pdf.RedactRegionOnPage(5, witnessSignature)

pdf.SaveAs("multi-page-application-redacted.pdf")
$vbLabelText   $csharpLabel

Los documentos con diseños coherentes se benefician de las definiciones de regiones reutilizables:

using IronPdf;
using IronSoftware.Drawing;

public class FormRegions
{
    // Standard form regions based on common templates
    public static RectangleF HeaderLogo => new RectangleF(20, 720, 150, 60);
    public static RectangleF SignatureBlock => new RectangleF(72, 72, 200, 50);
    public static RectangleF DateField => new RectangleF(400, 72, 120, 20);
    public static RectangleF PhotoId => new RectangleF(480, 650, 100, 130);
    public static RectangleF AddressBlock => new RectangleF(72, 600, 250, 80);
}

class Program
{
    static void Main()
    {
        PdfDocument pdf = PdfDocument.FromFile("standard-form.pdf");

        // Apply standard redactions using predefined regions
        pdf.RedactRegionsOnAllPages(FormRegions.SignatureBlock);
        pdf.RedactRegionsOnAllPages(FormRegions.DateField);
        pdf.RedactRegionOnPage(0, FormRegions.PhotoId);

        pdf.SaveAs("standard-form-redacted.pdf");
    }
}
using IronPdf;
using IronSoftware.Drawing;

public class FormRegions
{
    // Standard form regions based on common templates
    public static RectangleF HeaderLogo => new RectangleF(20, 720, 150, 60);
    public static RectangleF SignatureBlock => new RectangleF(72, 72, 200, 50);
    public static RectangleF DateField => new RectangleF(400, 72, 120, 20);
    public static RectangleF PhotoId => new RectangleF(480, 650, 100, 130);
    public static RectangleF AddressBlock => new RectangleF(72, 600, 250, 80);
}

class Program
{
    static void Main()
    {
        PdfDocument pdf = PdfDocument.FromFile("standard-form.pdf");

        // Apply standard redactions using predefined regions
        pdf.RedactRegionsOnAllPages(FormRegions.SignatureBlock);
        pdf.RedactRegionsOnAllPages(FormRegions.DateField);
        pdf.RedactRegionOnPage(0, FormRegions.PhotoId);

        pdf.SaveAs("standard-form-redacted.pdf");
    }
}
Imports IronPdf
Imports IronSoftware.Drawing

Public Class FormRegions
    ' Standard form regions based on common templates
    Public Shared ReadOnly Property HeaderLogo As RectangleF
        Get
            Return New RectangleF(20, 720, 150, 60)
        End Get
    End Property

    Public Shared ReadOnly Property SignatureBlock As RectangleF
        Get
            Return New RectangleF(72, 72, 200, 50)
        End Get
    End Property

    Public Shared ReadOnly Property DateField As RectangleF
        Get
            Return New RectangleF(400, 72, 120, 20)
        End Get
    End Property

    Public Shared ReadOnly Property PhotoId As RectangleF
        Get
            Return New RectangleF(480, 650, 100, 130)
        End Get
    End Property

    Public Shared ReadOnly Property AddressBlock As RectangleF
        Get
            Return New RectangleF(72, 600, 250, 80)
        End Get
    End Property
End Class

Module Program
    Sub Main()
        Dim pdf As PdfDocument = PdfDocument.FromFile("standard-form.pdf")

        ' Apply standard redactions using predefined regions
        pdf.RedactRegionsOnAllPages(FormRegions.SignatureBlock)
        pdf.RedactRegionsOnAllPages(FormRegions.DateField)
        pdf.RedactRegionOnPage(0, FormRegions.PhotoId)

        pdf.SaveAs("standard-form-redacted.pdf")
    End Sub
End Module
$vbLabelText   $csharpLabel

¿Cómo puedo eliminar metadatos que podrían exponer información confidencial?

Los metadatos PDF representan una fuente de fuga de información que a menudo se pasa por alto. Todos los PDF contienen propiedades que pueden revelar datos confidenciales: el nombre del autor y su nombre de usuario, el software utilizado para crear el documento, las marcas de tiempo de creación y modificación, el nombre original del archivo, el historial de revisiones y las propiedades personalizadas añadidas por diversas aplicaciones. Antes de compartir los documentos externamente, es esencial eliminar o desinfectar estos metadatos. Para obtener una visión general de las operaciones de metadatos, consulte nuestra guía práctica de metadatos.

IronPDF expone los metadatos del documento a través de la propiedad MetaData, lo que permite leer los valores existentes, modificarlos o eliminarlos por completo.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/view-metadata.cs
using IronPdf;

// Load a document containing sensitive metadata
PdfDocument pdf = PdfDocument.FromFile("internal-report.pdf");

// Access current metadata properties
string author = pdf.MetaData.Author;
string title = pdf.MetaData.Title;
string subject = pdf.MetaData.Subject;
string keywords = pdf.MetaData.Keywords;
string creator = pdf.MetaData.Creator;
string producer = pdf.MetaData.Producer;
DateTime? creationDate = pdf.MetaData.CreationDate;
DateTime? modifiedDate = pdf.MetaData.ModifiedDate;

// Get all metadata keys including custom properties
var allKeys = pdf.MetaData.Keys();
Imports IronPdf

' Load a document containing sensitive metadata
Dim pdf As PdfDocument = PdfDocument.FromFile("internal-report.pdf")

' Access current metadata properties
Dim author As String = pdf.MetaData.Author
Dim title As String = pdf.MetaData.Title
Dim subject As String = pdf.MetaData.Subject
Dim keywords As String = pdf.MetaData.Keywords
Dim creator As String = pdf.MetaData.Creator
Dim producer As String = pdf.MetaData.Producer
Dim creationDate As DateTime? = pdf.MetaData.CreationDate
Dim modifiedDate As DateTime? = pdf.MetaData.ModifiedDate

' Get all metadata keys including custom properties
Dim allKeys = pdf.MetaData.Keys()
$vbLabelText   $csharpLabel

Eliminar los metadatos sensibles antes de la distribución:

Entrada

Un memorando interno que contiene metadatos incrustados, como nombres de autores, marcas de tiempo de creación y propiedades personalizadas que podrían revelar información confidencial de la organización.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/remove-metadata.cs
using IronPdf;
using System;

PdfDocument pdf = PdfDocument.FromFile("confidential-memo.pdf");

// Replace identifying metadata with generic values
pdf.MetaData.Author = "Organization Name";
pdf.MetaData.Creator = "Document System";
pdf.MetaData.Producer = "";
pdf.MetaData.Title = "Public Document";
pdf.MetaData.Subject = "";
pdf.MetaData.Keywords = "";

// Normalize dates to remove timing information
pdf.MetaData.CreationDate = DateTime.Now;
pdf.MetaData.ModifiedDate = DateTime.Now;

// Remove specific custom metadata keys
pdf.MetaData.RemoveMetaDataKey("OriginalFilename");
pdf.MetaData.RemoveMetaDataKey("LastSavedBy");
pdf.MetaData.RemoveMetaDataKey("Company");
pdf.MetaData.RemoveMetaDataKey("Manager");

// Remove custom properties added by applications
try
{
    pdf.MetaData.CustomProperties.Remove("SourcePath");
}
catch { }

pdf.SaveAs("confidential-memo-cleaned.pdf");
Imports IronPdf
Imports System

Dim pdf As PdfDocument = PdfDocument.FromFile("confidential-memo.pdf")

' Replace identifying metadata with generic values
pdf.MetaData.Author = "Organization Name"
pdf.MetaData.Creator = "Document System"
pdf.MetaData.Producer = ""
pdf.MetaData.Title = "Public Document"
pdf.MetaData.Subject = ""
pdf.MetaData.Keywords = ""

' Normalize dates to remove timing information
pdf.MetaData.CreationDate = DateTime.Now
pdf.MetaData.ModifiedDate = DateTime.Now

' Remove specific custom metadata keys
pdf.MetaData.RemoveMetaDataKey("OriginalFilename")
pdf.MetaData.RemoveMetaDataKey("LastSavedBy")
pdf.MetaData.RemoveMetaDataKey("Company")
pdf.MetaData.RemoveMetaDataKey("Manager")

' Remove custom properties added by applications
Try
    pdf.MetaData.CustomProperties.Remove("SourcePath")
Catch
End Try

pdf.SaveAs("confidential-memo-cleaned.pdf")
$vbLabelText   $csharpLabel

Este código sustituye los campos de metadatos identificativos por valores genéricos, normaliza las marcas de tiempo a la fecha actual y elimina las claves de metadatos personalizadas que las aplicaciones puedan haber añadido. El método RemoveMetaDataKey se dirige a propiedades específicas como "OriginalFilename" y "LastSavedBy" que podrían exponer información interna.

Muestra de resultado

La limpieza exhaustiva de metadatos en operaciones por lotes requiere un enfoque sistemático:

using IronPdf;
using System;
using System.Collections.Generic;

public class MetadataCleaner
{
    private readonly string _defaultAuthor;
    private readonly string _defaultCreator;

    public MetadataCleaner(string organizationName)
    {
        _defaultAuthor = organizationName;
        _defaultCreator = $"{organizationName} Document System";
    }

    public void CleanMetadata(PdfDocument pdf)
    {
        // Replace standard metadata fields
        pdf.MetaData.Author = _defaultAuthor;
        pdf.MetaData.Creator = _defaultCreator;
        pdf.MetaData.Producer = "";
        pdf.MetaData.Subject = "";
        pdf.MetaData.Keywords = "";

        // Normalize timestamps
        DateTime now = DateTime.Now;
        pdf.MetaData.CreationDate = now;
        pdf.MetaData.ModifiedDate = now;

        // Get all keys and remove potentially sensitive ones
        List<string> keysToRemove = new List<string>();
        foreach (string key in pdf.MetaData.Keys())
        {
            // Keep only essential keys
            if (!IsEssentialKey(key))
            {
                keysToRemove.Add(key);
            }
        }

        foreach (string key in keysToRemove)
        {
            pdf.MetaData.RemoveMetaDataKey(key);
        }
    }

    private bool IsEssentialKey(string key)
    {
        // Keep only the basic display properties
        string[] essentialKeys = { "Title", "Author", "CreationDate", "ModifiedDate" };
        foreach (string essential in essentialKeys)
        {
            if (key.Equals(essential, StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }
        }
        return false;
    }
}

// Usage
class Program
{
    static void Main()
    {
        MetadataCleaner cleaner = new MetadataCleaner("Acme Corporation");

        PdfDocument pdf = PdfDocument.FromFile("report.pdf");
        cleaner.CleanMetadata(pdf);
        pdf.SaveAs("report-clean.pdf");
    }
}
using IronPdf;
using System;
using System.Collections.Generic;

public class MetadataCleaner
{
    private readonly string _defaultAuthor;
    private readonly string _defaultCreator;

    public MetadataCleaner(string organizationName)
    {
        _defaultAuthor = organizationName;
        _defaultCreator = $"{organizationName} Document System";
    }

    public void CleanMetadata(PdfDocument pdf)
    {
        // Replace standard metadata fields
        pdf.MetaData.Author = _defaultAuthor;
        pdf.MetaData.Creator = _defaultCreator;
        pdf.MetaData.Producer = "";
        pdf.MetaData.Subject = "";
        pdf.MetaData.Keywords = "";

        // Normalize timestamps
        DateTime now = DateTime.Now;
        pdf.MetaData.CreationDate = now;
        pdf.MetaData.ModifiedDate = now;

        // Get all keys and remove potentially sensitive ones
        List<string> keysToRemove = new List<string>();
        foreach (string key in pdf.MetaData.Keys())
        {
            // Keep only essential keys
            if (!IsEssentialKey(key))
            {
                keysToRemove.Add(key);
            }
        }

        foreach (string key in keysToRemove)
        {
            pdf.MetaData.RemoveMetaDataKey(key);
        }
    }

    private bool IsEssentialKey(string key)
    {
        // Keep only the basic display properties
        string[] essentialKeys = { "Title", "Author", "CreationDate", "ModifiedDate" };
        foreach (string essential in essentialKeys)
        {
            if (key.Equals(essential, StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }
        }
        return false;
    }
}

// Usage
class Program
{
    static void Main()
    {
        MetadataCleaner cleaner = new MetadataCleaner("Acme Corporation");

        PdfDocument pdf = PdfDocument.FromFile("report.pdf");
        cleaner.CleanMetadata(pdf);
        pdf.SaveAs("report-clean.pdf");
    }
}
Imports IronPdf
Imports System
Imports System.Collections.Generic

Public Class MetadataCleaner
    Private ReadOnly _defaultAuthor As String
    Private ReadOnly _defaultCreator As String

    Public Sub New(organizationName As String)
        _defaultAuthor = organizationName
        _defaultCreator = $"{organizationName} Document System"
    End Sub

    Public Sub CleanMetadata(pdf As PdfDocument)
        ' Replace standard metadata fields
        pdf.MetaData.Author = _defaultAuthor
        pdf.MetaData.Creator = _defaultCreator
        pdf.MetaData.Producer = ""
        pdf.MetaData.Subject = ""
        pdf.MetaData.Keywords = ""

        ' Normalize timestamps
        Dim now As DateTime = DateTime.Now
        pdf.MetaData.CreationDate = now
        pdf.MetaData.ModifiedDate = now

        ' Get all keys and remove potentially sensitive ones
        Dim keysToRemove As New List(Of String)()
        For Each key As String In pdf.MetaData.Keys()
            ' Keep only essential keys
            If Not IsEssentialKey(key) Then
                keysToRemove.Add(key)
            End If
        Next

        For Each key As String In keysToRemove
            pdf.MetaData.RemoveMetaDataKey(key)
        Next
    End Sub

    Private Function IsEssentialKey(key As String) As Boolean
        ' Keep only the basic display properties
        Dim essentialKeys As String() = {"Title", "Author", "CreationDate", "ModifiedDate"}
        For Each essential As String In essentialKeys
            If key.Equals(essential, StringComparison.OrdinalIgnoreCase) Then
                Return True
            End If
        Next
        Return False
    End Function
End Class

' Usage
Class Program
    Shared Sub Main()
        Dim cleaner As New MetadataCleaner("Acme Corporation")

        Dim pdf As PdfDocument = PdfDocument.FromFile("report.pdf")
        cleaner.CleanMetadata(pdf)
        pdf.SaveAs("report-clean.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

¿Cómo puedo desinfectar un PDF para eliminar scripts incrustados y amenazas ocultas?

La desinfección de PDF aborda problemas de seguridad que van más allá del contenido visible y los metadatos. Los archivos PDF pueden contener código JavaScript, ejecutables incrustados, acciones de formulario que activan conexiones externas y otros elementos potencialmente maliciosos. Estas capacidades existen para fines legítimos como formularios interactivos y contenido multimedia, pero también crean vectores de ataque. Al desinfectar un PDF se eliminan estos elementos activos y se conserva el contenido visual. Para obtener más información sobre los métodos de desinfección, consulte nuestra guía práctica de desinfección de PDF.

La clase Cleaner de IronPDF se encarga de la limpieza mediante un enfoque elegante: convertir el PDF a un formato de imagen y luego volver a convertirlo. Este proceso elimina JavaScript, objetos incrustados, acciones de formulario y anotaciones, manteniendo intacto el aspecto visual. La biblioteca ofrece dos métodos de desinfección con características diferentes.

Entrada

Un documento PDF recibido de una fuente externa que puede contener JavaScript, objetos incrustados u otro contenido activo potencialmente malicioso.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/sanitize-pdf.cs
using IronPdf;

// Load a PDF that may contain active content
PdfDocument pdf = PdfDocument.FromFile("received-document.pdf");

// Sanitize using SVG conversion
// Faster processing, results in searchable text, slight layout variations possible
PdfDocument sanitizedSvg = Cleaner.SanitizeWithSvg(pdf);
sanitizedSvg.SaveAs("sanitized-svg.pdf");

// Sanitize using Bitmap conversion
// Slower processing, text becomes image (not searchable), exact visual reproduction
PdfDocument sanitizedBitmap = Cleaner.SanitizeWithBitmap(pdf);
sanitizedBitmap.SaveAs("sanitized-bitmap.pdf");
Imports IronPdf

' Load a PDF that may contain active content
Dim pdf As PdfDocument = PdfDocument.FromFile("received-document.pdf")

' Sanitize using SVG conversion
' Faster processing, results in searchable text, slight layout variations possible
Dim sanitizedSvg As PdfDocument = Cleaner.SanitizeWithSvg(pdf)
sanitizedSvg.SaveAs("sanitized-svg.pdf")

' Sanitize using Bitmap conversion
' Slower processing, text becomes image (not searchable), exact visual reproduction
Dim sanitizedBitmap As PdfDocument = Cleaner.SanitizeWithBitmap(pdf)
sanitizedBitmap.SaveAs("sanitized-bitmap.pdf")
$vbLabelText   $csharpLabel

Este código demuestra dos métodos de limpieza proporcionados por la clase Cleaner de IronPDF. SanitizeWithSvg convierte el PDF a través de un formato intermedio SVG, preservando el texto que se puede buscar y eliminando el contenido activo. SanitizeWithBitmap convierte primero las páginas en imágenes, produciendo copias visuales exactas pero con el texto renderizado como gráficos no buscables.

Muestra de resultado

El método SVG es más rápido y conserva el texto como contenido que permite búsquedas, por lo que es adecuado para documentos que deben permanecer indexados o accesibles. El método de mapa de bits produce copias visuales exactas, pero convierte el texto en imágenes, lo que impide la selección y búsqueda de texto. Elija en función de sus requisitos para el documento de salida.

También puede aplicar opciones de renderizado durante la limpieza para ajustar el resultado:

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/sanitize-with-options.cs
using IronPdf;

// Load the potentially unsafe document
PdfDocument pdf = PdfDocument.FromFile("untrusted-source.pdf");

// Configure rendering options for sanitization
var renderOptions = new ChromePdfRenderOptions
{
    MarginTop = 10,
    MarginBottom = 10,
    MarginLeft = 10,
    MarginRight = 10
};

// Sanitize with custom options
PdfDocument sanitized = Cleaner.SanitizeWithSvg(pdf, renderOptions);
sanitized.SaveAs("untrusted-source-safe.pdf");
Imports IronPdf

' Load the potentially unsafe document
Dim pdf As PdfDocument = PdfDocument.FromFile("untrusted-source.pdf")

' Configure rendering options for sanitization
Dim renderOptions As New ChromePdfRenderOptions With {
    .MarginTop = 10,
    .MarginBottom = 10,
    .MarginLeft = 10,
    .MarginRight = 10
}

' Sanitize with custom options
Dim sanitized As PdfDocument = Cleaner.SanitizeWithSvg(pdf, renderOptions)
sanitized.SaveAs("untrusted-source-safe.pdf")
$vbLabelText   $csharpLabel

Los entornos de alta seguridad a menudo requieren combinar la desinfección con otras medidas de protección:

using IronPdf;
using System;

public class SecureDocumentProcessor
{
    public PdfDocument ProcessUntrustedDocument(string inputPath)
    {
        // Load the document
        PdfDocument original = PdfDocument.FromFile(inputPath);

        // Step 1: Sanitize to remove active content
        PdfDocument sanitized = Cleaner.SanitizeWithSvg(original);

        // Step 2: Clean metadata
        sanitized.MetaData.Author = "Processed Document";
        sanitized.MetaData.Creator = "Secure Processor";
        sanitized.MetaData.Producer = "";
        sanitized.MetaData.CreationDate = DateTime.Now;
        sanitized.MetaData.ModifiedDate = DateTime.Now;

        // Remove all custom metadata
        foreach (string key in sanitized.MetaData.Keys())
        {
            if (key != "Title" && key != "Author" && key != "CreationDate" && key != "ModifiedDate")
            {
                sanitized.MetaData.RemoveMetaDataKey(key);
            }
        }

        return sanitized;
    }
}

// Usage
class Program
{
    static void Main()
    {
        SecureDocumentProcessor processor = new SecureDocumentProcessor();
        PdfDocument safe = processor.ProcessUntrustedDocument("email-attachment.pdf");
        safe.SaveAs("email-attachment-safe.pdf");
    }
}
using IronPdf;
using System;

public class SecureDocumentProcessor
{
    public PdfDocument ProcessUntrustedDocument(string inputPath)
    {
        // Load the document
        PdfDocument original = PdfDocument.FromFile(inputPath);

        // Step 1: Sanitize to remove active content
        PdfDocument sanitized = Cleaner.SanitizeWithSvg(original);

        // Step 2: Clean metadata
        sanitized.MetaData.Author = "Processed Document";
        sanitized.MetaData.Creator = "Secure Processor";
        sanitized.MetaData.Producer = "";
        sanitized.MetaData.CreationDate = DateTime.Now;
        sanitized.MetaData.ModifiedDate = DateTime.Now;

        // Remove all custom metadata
        foreach (string key in sanitized.MetaData.Keys())
        {
            if (key != "Title" && key != "Author" && key != "CreationDate" && key != "ModifiedDate")
            {
                sanitized.MetaData.RemoveMetaDataKey(key);
            }
        }

        return sanitized;
    }
}

// Usage
class Program
{
    static void Main()
    {
        SecureDocumentProcessor processor = new SecureDocumentProcessor();
        PdfDocument safe = processor.ProcessUntrustedDocument("email-attachment.pdf");
        safe.SaveAs("email-attachment-safe.pdf");
    }
}
Imports IronPdf
Imports System

Public Class SecureDocumentProcessor
    Public Function ProcessUntrustedDocument(inputPath As String) As PdfDocument
        ' Load the document
        Dim original As PdfDocument = PdfDocument.FromFile(inputPath)

        ' Step 1: Sanitize to remove active content
        Dim sanitized As PdfDocument = Cleaner.SanitizeWithSvg(original)

        ' Step 2: Clean metadata
        sanitized.MetaData.Author = "Processed Document"
        sanitized.MetaData.Creator = "Secure Processor"
        sanitized.MetaData.Producer = ""
        sanitized.MetaData.CreationDate = DateTime.Now
        sanitized.MetaData.ModifiedDate = DateTime.Now

        ' Remove all custom metadata
        For Each key As String In sanitized.MetaData.Keys()
            If key <> "Title" AndAlso key <> "Author" AndAlso key <> "CreationDate" AndAlso key <> "ModifiedDate" Then
                sanitized.MetaData.RemoveMetaDataKey(key)
            End If
        Next

        Return sanitized
    End Function
End Class

' Usage
Module Program
    Sub Main()
        Dim processor As New SecureDocumentProcessor()
        Dim safe As PdfDocument = processor.ProcessUntrustedDocument("email-attachment.pdf")
        safe.SaveAs("email-attachment-safe.pdf")
    End Sub
End Module
$vbLabelText   $csharpLabel

¿Cómo buscar vulnerabilidades de seguridad en un PDF?

Antes de procesar o desinfectar los documentos, conviene evaluar qué amenazas potenciales contienen. El método Cleaner.ScanPdf de IronPDF examina los documentos utilizando reglas YARA, que son definiciones de patrones utilizadas habitualmente en el análisis de malware y la detección de amenazas. El análisis identifica las características asociadas a los archivos PDF maliciosos.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/scan-vulnerabilities.cs
using IronPdf;

// Load the document to scan
PdfDocument pdf = PdfDocument.FromFile("suspicious-document.pdf");

// Scan using default YARA rules
CleanerScanResult scanResult = Cleaner.ScanPdf(pdf);

// Check the scan results
bool threatsDetected = scanResult.IsDetected;
int riskCount = scanResult.Risks.Count;

// Process identified risks
if (scanResult.IsDetected)
{
    foreach (var risk in scanResult.Risks)
    {
        // Handle each identified risk
    }

    // Sanitize the document before use
    PdfDocument sanitized = Cleaner.SanitizeWithSvg(pdf);
    sanitized.SaveAs("suspicious-document-safe.pdf");
}
Imports IronPdf

' Load the document to scan
Dim pdf As PdfDocument = PdfDocument.FromFile("suspicious-document.pdf")

' Scan using default YARA rules
Dim scanResult As CleanerScanResult = Cleaner.ScanPdf(pdf)

' Check the scan results
Dim threatsDetected As Boolean = scanResult.IsDetected
Dim riskCount As Integer = scanResult.Risks.Count

' Process identified risks
If scanResult.IsDetected Then
    For Each risk In scanResult.Risks
        ' Handle each identified risk
    Next

    ' Sanitize the document before use
    Dim sanitized As PdfDocument = Cleaner.SanitizeWithSvg(pdf)
    sanitized.SaveAs("suspicious-document-safe.pdf")
End If
$vbLabelText   $csharpLabel

Puede proporcionar archivos de reglas YARA personalizados para requisitos de detección especializados. Las organizaciones con modelos de amenazas específicos o necesidades de cumplimiento suelen mantener sus propios conjuntos de reglas dirigidos a patrones de vulnerabilidad concretos.

:path=/static-assets/pdf/content-code-examples/tutorials/pdf-redaction-csharp/scan-custom-yara.cs
using IronPdf;

PdfDocument pdf = PdfDocument.FromFile("incoming-document.pdf");

// Scan with custom YARA rules
string[] customYaraFiles = { "corporate-rules.yar", "industry-specific.yar" };
CleanerScanResult result = Cleaner.ScanPdf(pdf, customYaraFiles);

if (result.IsDetected)
{
    // Document triggered custom rules and requires review or sanitization
    PdfDocument sanitized = Cleaner.SanitizeWithSvg(pdf);
    sanitized.SaveAs("incoming-document-safe.pdf");
}
Imports IronPdf

Dim pdf As PdfDocument = PdfDocument.FromFile("incoming-document.pdf")

' Scan with custom YARA rules
Dim customYaraFiles As String() = {"corporate-rules.yar", "industry-specific.yar"}
Dim result As CleanerScanResult = Cleaner.ScanPdf(pdf, customYaraFiles)

If result.IsDetected Then
    ' Document triggered custom rules and requires review or sanitization
    Dim sanitized As PdfDocument = Cleaner.SanitizeWithSvg(pdf)
    sanitized.SaveAs("incoming-document-safe.pdf")
End If
$vbLabelText   $csharpLabel

La integración de la digitalización en los flujos de trabajo de admisión de documentos ayuda a automatizar las decisiones de seguridad:

using IronPdf;
using System;
using System.IO;

public enum DocumentSafetyLevel
{
    Safe,
    Suspicious,
    Dangerous
}

public class DocumentSecurityGateway
{
    public DocumentSafetyLevel EvaluateDocument(string filePath)
    {
        PdfDocument pdf = PdfDocument.FromFile(filePath);
        CleanerScanResult scan = Cleaner.ScanPdf(pdf);

        if (!scan.IsDetected)
        {
            return DocumentSafetyLevel.Safe;
        }

        // Evaluate severity based on number of risks
        if (scan.Risks.Count > 5)
        {
            return DocumentSafetyLevel.Dangerous;
        }

        return DocumentSafetyLevel.Suspicious;
    }

    public PdfDocument ProcessIncomingDocument(string filePath, string outputDirectory)
    {
        DocumentSafetyLevel safety = EvaluateDocument(filePath);
        string fileName = Path.GetFileName(filePath);

        switch (safety)
        {
            case DocumentSafetyLevel.Safe:
                return PdfDocument.FromFile(filePath);

            case DocumentSafetyLevel.Suspicious:
                PdfDocument suspicious = PdfDocument.FromFile(filePath);
                return Cleaner.SanitizeWithSvg(suspicious);

            case DocumentSafetyLevel.Dangerous:
                throw new SecurityException($"Document {fileName} contains dangerous content");

            default:
                throw new InvalidOperationException("Unknown safety level");
        }
    }
}
using IronPdf;
using System;
using System.IO;

public enum DocumentSafetyLevel
{
    Safe,
    Suspicious,
    Dangerous
}

public class DocumentSecurityGateway
{
    public DocumentSafetyLevel EvaluateDocument(string filePath)
    {
        PdfDocument pdf = PdfDocument.FromFile(filePath);
        CleanerScanResult scan = Cleaner.ScanPdf(pdf);

        if (!scan.IsDetected)
        {
            return DocumentSafetyLevel.Safe;
        }

        // Evaluate severity based on number of risks
        if (scan.Risks.Count > 5)
        {
            return DocumentSafetyLevel.Dangerous;
        }

        return DocumentSafetyLevel.Suspicious;
    }

    public PdfDocument ProcessIncomingDocument(string filePath, string outputDirectory)
    {
        DocumentSafetyLevel safety = EvaluateDocument(filePath);
        string fileName = Path.GetFileName(filePath);

        switch (safety)
        {
            case DocumentSafetyLevel.Safe:
                return PdfDocument.FromFile(filePath);

            case DocumentSafetyLevel.Suspicious:
                PdfDocument suspicious = PdfDocument.FromFile(filePath);
                return Cleaner.SanitizeWithSvg(suspicious);

            case DocumentSafetyLevel.Dangerous:
                throw new SecurityException($"Document {fileName} contains dangerous content");

            default:
                throw new InvalidOperationException("Unknown safety level");
        }
    }
}
Imports IronPdf
Imports System
Imports System.IO

Public Enum DocumentSafetyLevel
    Safe
    Suspicious
    Dangerous
End Enum

Public Class DocumentSecurityGateway
    Public Function EvaluateDocument(filePath As String) As DocumentSafetyLevel
        Dim pdf As PdfDocument = PdfDocument.FromFile(filePath)
        Dim scan As CleanerScanResult = Cleaner.ScanPdf(pdf)

        If Not scan.IsDetected Then
            Return DocumentSafetyLevel.Safe
        End If

        ' Evaluate severity based on number of risks
        If scan.Risks.Count > 5 Then
            Return DocumentSafetyLevel.Dangerous
        End If

        Return DocumentSafetyLevel.Suspicious
    End Function

    Public Function ProcessIncomingDocument(filePath As String, outputDirectory As String) As PdfDocument
        Dim safety As DocumentSafetyLevel = EvaluateDocument(filePath)
        Dim fileName As String = Path.GetFileName(filePath)

        Select Case safety
            Case DocumentSafetyLevel.Safe
                Return PdfDocument.FromFile(filePath)

            Case DocumentSafetyLevel.Suspicious
                Dim suspicious As PdfDocument = PdfDocument.FromFile(filePath)
                Return Cleaner.SanitizeWithSvg(suspicious)

            Case DocumentSafetyLevel.Dangerous
                Throw New SecurityException($"Document {fileName} contains dangerous content")

            Case Else
                Throw New InvalidOperationException("Unknown safety level")
        End Select
    End Function
End Class
$vbLabelText   $csharpLabel

¿Cómo puedo crear una cadena completa de redacción y desinfección?

El procesamiento de documentos de producción suele requerir la combinación de varias técnicas de protección en un flujo de trabajo cohesivo. Un proceso completo podría escanear los documentos entrantes en busca de amenazas, desinfectar los que pasen el filtro inicial, aplicar redacciones de texto y regiones, eliminar metadatos y producir registros de auditoría que documenten todas las acciones realizadas. Este ejemplo muestra un enfoque integrado de este tipo.

using IronPdf;
using IronSoftware.Drawing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;

public class DocumentProcessingResult
{
    public string OriginalFile { get; set; }
    public string OutputFile { get; set; }
    public bool WasSanitized { get; set; }
    public int TextRedactionsApplied { get; set; }
    public int RegionRedactionsApplied { get; set; }
    public bool MetadataCleaned { get; set; }
    public List<string> SensitiveDataTypesFound { get; set; } = new List<string>();
    public DateTime ProcessedAt { get; set; }
    public bool Success { get; set; }
    public string ErrorMessage { get; set; }
}

public class ComprehensiveDocumentProcessor
{
    // Sensitive data patterns
    private readonly Dictionary<string, string> _sensitivePatterns = new Dictionary<string, string>
    {
        { "SSN", @"\b\d{3}-\d{2}-\d{4}\b" },
        { "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
        { "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
        { "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" }
    };

    // Standard regions to redact (signature areas, photo locations)
    private readonly List<RectangleF> _standardRedactionRegions = new List<RectangleF>
    {
        new RectangleF(72, 72, 200, 50),    // Bottom left signature
        new RectangleF(350, 72, 200, 50)    // Bottom right signature
    };

    private readonly string _organizationName;

    public ComprehensiveDocumentProcessor(string organizationName)
    {
        _organizationName = organizationName;
    }

    public DocumentProcessingResult ProcessDocument(
        string inputPath,
        string outputPath,
        bool sanitize = true,
        bool redactPatterns = true,
        bool redactRegions = true,
        bool cleanMetadata = true,
        List<string> additionalTermsToRedact = null)
    {
        var result = new DocumentProcessingResult
        {
            OriginalFile = inputPath,
            OutputFile = outputPath,
            ProcessedAt = DateTime.Now
        };

        try
        {
            // Load the document
            PdfDocument pdf = PdfDocument.FromFile(inputPath);

            // Step 1: Security scan
            CleanerScanResult scanResult = Cleaner.ScanPdf(pdf);

            if (scanResult.IsDetected && scanResult.Risks.Count > 10)
            {
                throw new SecurityException("Document contains too many security risks to process");
            }

            // Step 2: Sanitization (if needed or requested)
            if (sanitize || scanResult.IsDetected)
            {
                pdf = Cleaner.SanitizeWithSvg(pdf);
                result.WasSanitized = true;
            }

            // Step 3: Pattern-based text redaction
            if (redactPatterns)
            {
                string fullText = pdf.ExtractAllText();
                HashSet<string> valuesToRedact = new HashSet<string>();

                foreach (var pattern in _sensitivePatterns)
                {
                    Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
                    MatchCollection matches = regex.Matches(fullText);

                    if (matches.Count > 0)
                    {
                        result.SensitiveDataTypesFound.Add($"{pattern.Key} ({matches.Count})");
                        foreach (Match match in matches)
                        {
                            valuesToRedact.Add(match.Value);
                        }
                    }
                }

                // Apply redactions
                foreach (string value in valuesToRedact)
                {
                    pdf.RedactTextOnAllPages(value);
                    result.TextRedactionsApplied++;
                }
            }

            // Step 4: Additional specific terms
            if (additionalTermsToRedact != null)
            {
                foreach (string term in additionalTermsToRedact)
                {
                    pdf.RedactTextOnAllPages(term);
                    result.TextRedactionsApplied++;
                }
            }

            // Step 5: Region-based redaction
            if (redactRegions)
            {
                foreach (RectangleF region in _standardRedactionRegions)
                {
                    pdf.RedactRegionsOnAllPages(region);
                    result.RegionRedactionsApplied++;
                }
            }

            // Step 6: Metadata cleaning
            if (cleanMetadata)
            {
                pdf.MetaData.Author = _organizationName;
                pdf.MetaData.Creator = $"{_organizationName} Document Processor";
                pdf.MetaData.Producer = "";
                pdf.MetaData.Subject = "";
                pdf.MetaData.Keywords = "";
                pdf.MetaData.CreationDate = DateTime.Now;
                pdf.MetaData.ModifiedDate = DateTime.Now;
                result.MetadataCleaned = true;
            }

            // Step 7: Save the processed document
            pdf.SaveAs(outputPath);
            result.Success = true;
        }
        catch (Exception ex)
        {
            result.Success = false;
            result.ErrorMessage = ex.Message;
        }

        return result;
    }
}

// Usage example
class Program
{
    static void Main()
    {
        var processor = new ComprehensiveDocumentProcessor("Acme Corporation");

        // Process a single document with all protections
        var result = processor.ProcessDocument(
            inputPath: "customer-application.pdf",
            outputPath: "customer-application-redacted.pdf",
            sanitize: true,
            redactPatterns: true,
            redactRegions: true,
            cleanMetadata: true,
            additionalTermsToRedact: new List<string> { "Project Alpha", "Internal Use Only" }
        );

        // Batch process multiple documents
        string[] inputFiles = Directory.GetFiles("incoming", "*.pdf");
        foreach (string file in inputFiles)
        {
            string outputFile = Path.Combine("processed", Path.GetFileName(file));
            processor.ProcessDocument(file, outputFile);
        }
    }
}
using IronPdf;
using IronSoftware.Drawing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;

public class DocumentProcessingResult
{
    public string OriginalFile { get; set; }
    public string OutputFile { get; set; }
    public bool WasSanitized { get; set; }
    public int TextRedactionsApplied { get; set; }
    public int RegionRedactionsApplied { get; set; }
    public bool MetadataCleaned { get; set; }
    public List<string> SensitiveDataTypesFound { get; set; } = new List<string>();
    public DateTime ProcessedAt { get; set; }
    public bool Success { get; set; }
    public string ErrorMessage { get; set; }
}

public class ComprehensiveDocumentProcessor
{
    // Sensitive data patterns
    private readonly Dictionary<string, string> _sensitivePatterns = new Dictionary<string, string>
    {
        { "SSN", @"\b\d{3}-\d{2}-\d{4}\b" },
        { "Credit Card", @"\b(?:\d{4}[-\s]?){3}\d{1,4}\b" },
        { "Email", @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b" },
        { "Phone", @"\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b" }
    };

    // Standard regions to redact (signature areas, photo locations)
    private readonly List<RectangleF> _standardRedactionRegions = new List<RectangleF>
    {
        new RectangleF(72, 72, 200, 50),    // Bottom left signature
        new RectangleF(350, 72, 200, 50)    // Bottom right signature
    };

    private readonly string _organizationName;

    public ComprehensiveDocumentProcessor(string organizationName)
    {
        _organizationName = organizationName;
    }

    public DocumentProcessingResult ProcessDocument(
        string inputPath,
        string outputPath,
        bool sanitize = true,
        bool redactPatterns = true,
        bool redactRegions = true,
        bool cleanMetadata = true,
        List<string> additionalTermsToRedact = null)
    {
        var result = new DocumentProcessingResult
        {
            OriginalFile = inputPath,
            OutputFile = outputPath,
            ProcessedAt = DateTime.Now
        };

        try
        {
            // Load the document
            PdfDocument pdf = PdfDocument.FromFile(inputPath);

            // Step 1: Security scan
            CleanerScanResult scanResult = Cleaner.ScanPdf(pdf);

            if (scanResult.IsDetected && scanResult.Risks.Count > 10)
            {
                throw new SecurityException("Document contains too many security risks to process");
            }

            // Step 2: Sanitization (if needed or requested)
            if (sanitize || scanResult.IsDetected)
            {
                pdf = Cleaner.SanitizeWithSvg(pdf);
                result.WasSanitized = true;
            }

            // Step 3: Pattern-based text redaction
            if (redactPatterns)
            {
                string fullText = pdf.ExtractAllText();
                HashSet<string> valuesToRedact = new HashSet<string>();

                foreach (var pattern in _sensitivePatterns)
                {
                    Regex regex = new Regex(pattern.Value, RegexOptions.IgnoreCase);
                    MatchCollection matches = regex.Matches(fullText);

                    if (matches.Count > 0)
                    {
                        result.SensitiveDataTypesFound.Add($"{pattern.Key} ({matches.Count})");
                        foreach (Match match in matches)
                        {
                            valuesToRedact.Add(match.Value);
                        }
                    }
                }

                // Apply redactions
                foreach (string value in valuesToRedact)
                {
                    pdf.RedactTextOnAllPages(value);
                    result.TextRedactionsApplied++;
                }
            }

            // Step 4: Additional specific terms
            if (additionalTermsToRedact != null)
            {
                foreach (string term in additionalTermsToRedact)
                {
                    pdf.RedactTextOnAllPages(term);
                    result.TextRedactionsApplied++;
                }
            }

            // Step 5: Region-based redaction
            if (redactRegions)
            {
                foreach (RectangleF region in _standardRedactionRegions)
                {
                    pdf.RedactRegionsOnAllPages(region);
                    result.RegionRedactionsApplied++;
                }
            }

            // Step 6: Metadata cleaning
            if (cleanMetadata)
            {
                pdf.MetaData.Author = _organizationName;
                pdf.MetaData.Creator = $"{_organizationName} Document Processor";
                pdf.MetaData.Producer = "";
                pdf.MetaData.Subject = "";
                pdf.MetaData.Keywords = "";
                pdf.MetaData.CreationDate = DateTime.Now;
                pdf.MetaData.ModifiedDate = DateTime.Now;
                result.MetadataCleaned = true;
            }

            // Step 7: Save the processed document
            pdf.SaveAs(outputPath);
            result.Success = true;
        }
        catch (Exception ex)
        {
            result.Success = false;
            result.ErrorMessage = ex.Message;
        }

        return result;
    }
}

// Usage example
class Program
{
    static void Main()
    {
        var processor = new ComprehensiveDocumentProcessor("Acme Corporation");

        // Process a single document with all protections
        var result = processor.ProcessDocument(
            inputPath: "customer-application.pdf",
            outputPath: "customer-application-redacted.pdf",
            sanitize: true,
            redactPatterns: true,
            redactRegions: true,
            cleanMetadata: true,
            additionalTermsToRedact: new List<string> { "Project Alpha", "Internal Use Only" }
        );

        // Batch process multiple documents
        string[] inputFiles = Directory.GetFiles("incoming", "*.pdf");
        foreach (string file in inputFiles)
        {
            string outputFile = Path.Combine("processed", Path.GetFileName(file));
            processor.ProcessDocument(file, outputFile);
        }
    }
}
Imports IronPdf
Imports IronSoftware.Drawing
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Text.RegularExpressions

Public Class DocumentProcessingResult
    Public Property OriginalFile As String
    Public Property OutputFile As String
    Public Property WasSanitized As Boolean
    Public Property TextRedactionsApplied As Integer
    Public Property RegionRedactionsApplied As Integer
    Public Property MetadataCleaned As Boolean
    Public Property SensitiveDataTypesFound As List(Of String) = New List(Of String)()
    Public Property ProcessedAt As DateTime
    Public Property Success As Boolean
    Public Property ErrorMessage As String
End Class

Public Class ComprehensiveDocumentProcessor
    ' Sensitive data patterns
    Private ReadOnly _sensitivePatterns As Dictionary(Of String, String) = New Dictionary(Of String, String) From {
        {"SSN", "\b\d{3}-\d{2}-\d{4}\b"},
        {"Credit Card", "\b(?:\d{4}[-\s]?){3}\d{1,4}\b"},
        {"Email", "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"},
        {"Phone", "\b(?:\(\d{3}\)\s?|\d{3}[-.])\d{3}[-.]?\d{4}\b"}
    }

    ' Standard regions to redact (signature areas, photo locations)
    Private ReadOnly _standardRedactionRegions As List(Of RectangleF) = New List(Of RectangleF) From {
        New RectangleF(72, 72, 200, 50),    ' Bottom left signature
        New RectangleF(350, 72, 200, 50)    ' Bottom right signature
    }

    Private ReadOnly _organizationName As String

    Public Sub New(organizationName As String)
        _organizationName = organizationName
    End Sub

    Public Function ProcessDocument(
        inputPath As String,
        outputPath As String,
        Optional sanitize As Boolean = True,
        Optional redactPatterns As Boolean = True,
        Optional redactRegions As Boolean = True,
        Optional cleanMetadata As Boolean = True,
        Optional additionalTermsToRedact As List(Of String) = Nothing) As DocumentProcessingResult

        Dim result As New DocumentProcessingResult With {
            .OriginalFile = inputPath,
            .OutputFile = outputPath,
            .ProcessedAt = DateTime.Now
        }

        Try
            ' Load the document
            Dim pdf As PdfDocument = PdfDocument.FromFile(inputPath)

            ' Step 1: Security scan
            Dim scanResult As CleanerScanResult = Cleaner.ScanPdf(pdf)

            If scanResult.IsDetected AndAlso scanResult.Risks.Count > 10 Then
                Throw New SecurityException("Document contains too many security risks to process")
            End If

            ' Step 2: Sanitization (if needed or requested)
            If sanitize OrElse scanResult.IsDetected Then
                pdf = Cleaner.SanitizeWithSvg(pdf)
                result.WasSanitized = True
            End If

            ' Step 3: Pattern-based text redaction
            If redactPatterns Then
                Dim fullText As String = pdf.ExtractAllText()
                Dim valuesToRedact As New HashSet(Of String)()

                For Each pattern In _sensitivePatterns
                    Dim regex As New Regex(pattern.Value, RegexOptions.IgnoreCase)
                    Dim matches As MatchCollection = regex.Matches(fullText)

                    If matches.Count > 0 Then
                        result.SensitiveDataTypesFound.Add($"{pattern.Key} ({matches.Count})")
                        For Each match As Match In matches
                            valuesToRedact.Add(match.Value)
                        Next
                    End If
                Next

                ' Apply redactions
                For Each value As String In valuesToRedact
                    pdf.RedactTextOnAllPages(value)
                    result.TextRedactionsApplied += 1
                Next
            End If

            ' Step 4: Additional specific terms
            If additionalTermsToRedact IsNot Nothing Then
                For Each term As String In additionalTermsToRedact
                    pdf.RedactTextOnAllPages(term)
                    result.TextRedactionsApplied += 1
                Next
            End If

            ' Step 5: Region-based redaction
            If redactRegions Then
                For Each region As RectangleF In _standardRedactionRegions
                    pdf.RedactRegionsOnAllPages(region)
                    result.RegionRedactionsApplied += 1
                Next
            End If

            ' Step 6: Metadata cleaning
            If cleanMetadata Then
                pdf.MetaData.Author = _organizationName
                pdf.MetaData.Creator = $"{_organizationName} Document Processor"
                pdf.MetaData.Producer = ""
                pdf.MetaData.Subject = ""
                pdf.MetaData.Keywords = ""
                pdf.MetaData.CreationDate = DateTime.Now
                pdf.MetaData.ModifiedDate = DateTime.Now
                result.MetadataCleaned = True
            End If

            ' Step 7: Save the processed document
            pdf.SaveAs(outputPath)
            result.Success = True
        Catch ex As Exception
            result.Success = False
            result.ErrorMessage = ex.Message
        End Try

        Return result
    End Function
End Class

' Usage example
Class Program
    Shared Sub Main()
        Dim processor As New ComprehensiveDocumentProcessor("Acme Corporation")

        ' Process a single document with all protections
        Dim result = processor.ProcessDocument(
            inputPath:="customer-application.pdf",
            outputPath:="customer-application-redacted.pdf",
            sanitize:=True,
            redactPatterns:=True,
            redactRegions:=True,
            cleanMetadata:=True,
            additionalTermsToRedact:=New List(Of String) From {"Project Alpha", "Internal Use Only"}
        )

        ' Batch process multiple documents
        Dim inputFiles As String() = Directory.GetFiles("incoming", "*.pdf")
        For Each file As String In inputFiles
            Dim outputFile As String = Path.Combine("processed", Path.GetFileName(file))
            processor.ProcessDocument(file, outputFile)
        Next
    End Sub
End Class
$vbLabelText   $csharpLabel

Entrada

Un formulario de solicitud de cliente que contiene varios tipos de datos confidenciales, como números de seguro social, números de tarjetas de crédito, direcciones de correo electrónico y bloques de firmas que requieren una protección completa.

Muestra de resultado

Este completo procesador combina todas las técnicas tratadas en esta guía en una única clase configurable. Escanea en busca de amenazas, desinfecta cuando es necesario, encuentra y redacta patrones sensibles, aplica redacciones regionales, limpia metadatos y produce informes detallados. Puede ajustar los patrones de sensibilidad, las regiones de redacción y las opciones de procesamiento para que se ajusten a sus requisitos específicos.


Próximos pasos

Proteger la información confidencial de los documentos PDF requiere algo más que medidas superficiales. La redacción real elimina el contenido de la estructura del documento de forma permanente. La concordancia de patrones automatiza el descubrimiento y la eliminación de datos como números de la Seguridad Social, detalles de tarjetas de crédito y direcciones de correo electrónico. La redacción por regiones gestiona firmas, fotos y otros elementos gráficos que la concordancia de texto no puede abordar. La limpieza de metadatos elimina información oculta que podría revelar autores, marcas de tiempo o rutas internas de archivos. La sanitización elimina los scripts incrustados y el contenido activo que plantean riesgos de seguridad.

IronPDF ofrece todas estas funciones a través de una API coherente y bien diseñada que se integra de forma natural con las prácticas de desarrollo de C# y .NET. Los métodos que se muestran en esta guía se pueden aplicar a documentos individuales o a procesamiento por lotes de miles de archivos. Tanto si está creando flujos de trabajo de cumplimiento normativo para datos sanitarios, preparando documentos legales para descubrimiento, o simplemente asegurándose de que los informes internos se pueden compartir externamente de forma segura, estas técnicas forman la base del manejo responsable de documentos. Para una cobertura de seguridad completa, combine la redacción con protección de contraseñas y permisos y firmas digitales.

¿Listo para empezar a construir? Descargue IronPDF y pruébelo gratuitamente. La biblioteca incluye una licencia de desarrollo gratuita para que pueda evaluar a fondo las funciones de redacción, extracción de texto y desinfección antes de adquirir una licencia de producción. Si tiene alguna pregunta sobre la implementación o el cumplimiento de los flujos de trabajo, póngase en contacto con nuestro equipo de asistencia técnica.

Preguntas Frecuentes

¿Qué es la redacción de PDF?

La redacción de PDF es el proceso de eliminación permanente de información confidencial de un documento PDF. Puede incluir texto, imágenes y metadatos que deban ocultarse por motivos de privacidad o cumplimiento de normativas.

¿Cómo puedo redactar información en un PDF utilizando C#?

Puede utilizar IronPDF para redactar información en un PDF utilizando C#. Le permite eliminar u ocultar permanentemente texto, imágenes y metadatos en documentos PDF, garantizando que cumplen las normas de privacidad y conformidad.

¿Por qué es importante la redacción de PDF para cumplir la normativa?

La redacción de PDF es crucial para el cumplimiento de normas como HIPAA, GDPR y PCI DSS, ya que ayuda a proteger datos confidenciales y a evitar el acceso no autorizado a información confidencial.

¿Puede IronPDF redactar regiones enteras de un PDF?

Sí, IronPDF puede redactar regiones enteras de un PDF. Esto le permite definir áreas específicas dentro de un documento que deben ocultarse o eliminarse por motivos de seguridad.

¿Qué tipos de datos pueden redactarse con IronPDF?

IronPDF puede redactar varios tipos de datos, incluidos texto, imágenes y metadatos de documentos PDF, garantizando la privacidad y seguridad de los datos.

¿Admite IronPDF la desinfección de documentos?

Sí, IronPDF permite desinfectar documentos, lo que implica limpiar un PDF para eliminar datos ocultos o metadatos que pueden no ser visibles pero que podrían suponer un riesgo para la privacidad.

¿Es posible automatizar la redacción de PDF con IronPDF?

Sí, IronPDF permite automatizar los procesos de redacción de PDF en C#, lo que facilita la gestión de grandes volúmenes de documentos que requieren la eliminación de datos confidenciales.

¿Cómo garantiza IronPDF la permanencia de la redacción?

IronPDF garantiza la permanencia de la redacción mediante la eliminación permanente del texto y las imágenes seleccionados del documento, en lugar de simplemente oscurecerlos, lo que significa que no pueden recuperarse ni visualizarse.

¿Puede IronPDF redactar metadatos en un PDF?

Sí, IronPDF puede redactar metadatos en un documento PDF, garantizando que todas las formas de datos confidenciales, incluidos los datos ocultos o de fondo, se eliminen completamente.

¿Cuáles son las ventajas de utilizar IronPDF para la redacción de PDF?

El uso de IronPDF para la redacción de PDF ofrece ventajas como garantizar el cumplimiento de las normativas de protección de datos, mejorar la seguridad de los documentos y proporcionar un proceso eficaz y automatizado para la gestión de información confidencial.

Curtis Chau
Escritor Técnico

Curtis Chau tiene una licenciatura en Ciencias de la Computación (Carleton University) y se especializa en el desarrollo front-end con experiencia en Node.js, TypeScript, JavaScript y React. Apasionado por crear interfaces de usuario intuitivas y estéticamente agradables, disfruta trabajando con frameworks modernos y creando manuales bien ...

Leer más
¿Listo para empezar?
Nuget Descargas 17,386,124 | Versión: 2026.2 recién lanzado