Esta página puede contener texto traducido automáticamente.

Fusionar documentos PDF en C# y VB.NET

Las empresas suelen fusionar archivos PDF para archivar documentos. Si bien la combinación de PDF parece una tarea sencilla, existen muchos obstáculos. Debe combinar correctamente campos de formulario, marcadores, capas y otros objetos PDF. También debes evitar objetos duplicados para obtener un archivo de salida compacto.

La biblioteca Docotic.Pdf maneja todos los matices de fusión. Le permite combinar documentos PDF en sólo unas pocas líneas de código C# o VB.NET.

Combinar documentos PDF

Docotic.Pdf viene con licencias gratuitas y de pago. Puede descargar la biblioteca y obtener una clave de licencia de evaluación en la página de descarga de Docotic.Pdf.

Biblioteca Docotic.Pdf 9.4.17467-dev Pruebas de regresión 14,760 pasaron Descargas totales de NuGet 4,415,970

Conceptos básicos de fusión de PDF

Los métodos PdfDocument.Append le permiten agregar documentos PDF desde archivos, secuencias o matrices de bytes. También hay opciones para agregar archivos protegidos y fusionar campos de formulario.

Combina dos archivos PDF

Este código de muestra muestra cómo fusionar archivos PDF en C#:

using var pdf = new PdfDocument("first.pdf");
pdf.Append("second.pdf");
pdf.Save("merged.pdf");

Pruebe el ejemplo de código Fusionar dos documentos PDF de GitHub.

Combinar secuencias de PDF

Es fácil adaptar el ejemplo anterior para trabajar con secuencias en lugar de rutas de archivos. Aquí está el método auxiliar para fusionar transmisiones:

void Merge(Stream first, Stream second, Stream result)
{
    using var pdf = new PdfDocument(first);
    pdf.Append(second);
    pdf.Save(result);
}

Combina varios archivos PDF

Puede llamar repetidamente al método Append para agregar varios archivos PDF:

string[] filesToMerge = ..;
using var pdf = new PdfDocument();
foreach (string file in filesToMerge)
    pdf.Append(file);

// Eliminar la página vacía agregada por la llamada PdfDocument()
pdf.RemovePage(0);

pdf.Save(pathToFile);

Combina archivos PDF cifrados

Existen sobrecargas de Append para fusionar documentos cifrados:

using var pdf = new PdfDocument();
pdf.Append("encrypted.pdf", new PdfStandardDecryptionHandler("password"));
pdf.Save("merged.pdf");

Puede encontrar más información en el artículo Descifrar documentos PDF en C# y VB.NET.

Combinar formularios PDF

Cada campo de formulario en un documento PDF debe tener un nombre único. Esto podría generar un problema cuando los documentos a fusionar contengan campos con los mismos nombres. Docotic.Pdf proporciona las siguientes estrategias de combinación para controles de formulario en conflicto:

  • Cambiar el nombre de los controles agregados cuando entren en conflicto con los controles existentes
  • Fusionar controles agregados a controles existentes
  • Aplanar controles adjuntos
  • No agregue ningún control
  • Agregar controles tal cual

De forma predeterminada, la biblioteca cambia el nombre de los controles agregados en caso de conflicto. Puedes elegir una estrategia alternativa con la clase PdfMergingOptions:

using var pdf = new PdfDocument("form.pdf");

var decryptionHandler = new PdfStandardDecryptionHandler(string.Empty);
var mergingOptions = new PdfMergingOptions()
{
    ControlMergingMode = PdfControlMergingMode.CopyAsKids
};
pdf.Append("form.pdf", decryptionHandler, mergingOptions);

pdf.Save("merged.pdf");

Con el modo CopyAsKids, la biblioteca fusiona y sincroniza los controles en conflicto. Es decir, cuando cambies un control, el segundo tendrá el mismo valor.

Reducir el archivo PDF combinado

Los documentos PDF pueden contener objetos idénticos, como fuentes o imágenes. Cuando combine dichos documentos, el documento resultante contendrá copias de los mismos objetos. Utilice el método PdfDocument.ReplaceDuplicateObjects() para optimizar el resultado de la combinación:

using var pdf = new PdfDocument("2024-05-28.pdf");
pdf.Append("2024-05-29.pdf");

pdf.ReplaceDuplicateObjects();

pdf.Save("merged.pdf");

Puede reducir aún más el tamaño del archivo de salida. Por ejemplo, puede eliminar glifos de fuentes no utilizados o comprimir imágenes. Lea acerca de las opciones de compresión admitidas en el artículo Comprimir documentos PDF en C# y VB.NET.

Personalizar la combinación de PDF

Docotic.Pdf proporciona métodos para extraer, reordenar o eliminar páginas PDF. Puede usarlos con el método Append para implementar tareas personalizadas de combinación de PDF.

Agregar páginas PDF específicas

Docotic.Pdf también le permite fusionar una parte de un documento PDF. Hay diferentes maneras de hacerlo. Por ejemplo, puede dividir un documento PDF agregado y agregar páginas extraídas. El siguiente asistente de C# añade páginas seleccionadas al PdfDocument:

private static void AppendPart(PdfDocument pdf, string filePath, params int[] pagesToAppend)
{
    using var streamToAppend = new MemoryStream();
    using var other = new PdfDocument(filePath);
    using var extracted = other.CopyPages(pagesToAppend);
    var options = new PdfSaveOptions
    {
        UseObjectStreams = false
    };
    extracted.Save(streamToAppend, options);

    pdf.Append(streamToAppend);
}

O puede adjuntar un documento PDF completo y eliminar páginas innecesarias. El siguiente ejemplo de código agrega las dos primeras páginas del segundo.pdf:

using var pdf = new PdfDocument(@"first.pdf");

int pageCountBefore = pdf.PageCount;
pdf.Append(@"second.pdf");
pdf.RemovePages(pageCountBefore + 2);

pdf.Save(pathToFile);

Otra solución se relaciona con la imposición de PDF. Puedes leer sobre eso en la sección correspondiente.

Anteponer PDF

Los métodos Append siempre agregan páginas al final del documento actual. ¿Cómo fusionar archivos PDF en diferente orden? A veces puedes cambiar el orden de las llamadas Append. Es decir, utilice

pdf.Append("first.pdf");
pdf.Append("second.pdf");

en lugar de

pdf.Append("second.pdf");
pdf.Append("first.pdf");

O puede reordenar las páginas después de fusionarlas. Este código C# mueve el documento PDF adjunto al principio:

using var pdf = new PdfDocument(@"second.pdf");

int pageCountBefore = pdf.PageCount;
pdf.Append(@"first.pdf");
pdf.MovePages(pageCountBefore, pdf.PageCount - pageCountBefore, 0);

pdf.Save(pathToFile);

Ejemplos de códigos relacionados para reordenar páginas PDF:

Imponer PDF

Docotic.Pdf le permite combinar varias páginas PDF en una sola página. Utilice el método PdfDocument.CreateXObject(PdfPage) para crear un objeto PdfXObject basado en una página existente. Luego, dibuja este objeto con la escala deseada. Código de muestra:

using var src = new PdfDocument(@"src.pdf");
using var dest = new PdfDocument();
PdfXObject firstXObject = dest.CreateXObject(src.Pages[0]);
PdfXObject secondXObject = dest.CreateXObject(src.Pages[1]);

PdfPage page = dest.Pages[0];
page.Orientation = PdfPaperOrientation.Landscape;
double halfOfPage = page.Width / 2;
page.Canvas.DrawXObject(firstXObject, 0, 0, halfOfPage, page.Height, 0);
page.Canvas.DrawXObject(secondXObject, halfOfPage, 0, halfOfPage, page.Height, 0);

dest.Save("result.pdf");

Pruebe el proyecto de muestra relacionado Crear XObject desde la página de GitHub.

Fusionar como archivo adjunto

A veces, es posible que necesites incrustar un archivo PDF en otro como archivo adjunto. Eso también es posible. También puede agregar enlaces al archivo incrustado en páginas PDF:

using var pdf = new PdfDocument();

PdfFileSpecification first = pdf.CreateFileAttachment("first.pdf");
pdf.SharedAttachments.Add(first);

var bounds = new PdfRectangle(20, 70, 100, 100);
PdfFileSpecification fs = pdf.CreateFileAttachment("second.pdf");
pdf.Pages[0].AddFileAnnotation(bounds, fs);

pdf.Save("attachments.pdf");

Puede encontrar ejemplos de código relacionados en el grupo archivos adjuntos PDF en GitHub.

Fusionar en hilos paralelos

Al fusionar muchos archivos PDF, es posible paralelizar el código. La clase PdfDocument no es segura para subprocesos. Por lo tanto, necesitamos usar objetos PdfDocument separados en diferentes subprocesos. Mire el ejemplo de código Fusionar documentos PDF en hilos paralelos para obtener más detalles.

Este código muestra cómo puedes combinar secuencias de PDF en paralelo:

Stream[] documentsToMerge = ..;

int rangeSize = 50;
while (documentsToMerge.Length > rangeSize)
{
    int partitionCount = (int)Math.Ceiling(documentsToMerge.Length / (double)rangeSize);
    var result = new Stream[partitionCount];

    var partitioner = Partitioner.Create(0, documentsToMerge.Length, rangeSize);
    Parallel.ForEach(partitioner, range =>
    {
        int startIndex = range.Item1;
        int count = range.Item2 - range.Item1;
        result[startIndex / rangeSize] = MergeToStream(documentsToMerge, startIndex, count);
    });
    documentsToMerge = result;
}

using PdfDocument final = GetMergedDocument(documentsToMerge, 0, documentsToMerge.Length);
final.Save("merged.pdf");


private static Stream MergeToStream(Stream[] streams, int startIndex, int count)
{
    using PdfDocument pdf = GetMergedDocument(streams, startIndex, count);

    var result = new MemoryStream();

    var options = new PdfSaveOptions
    {
        UseObjectStreams = false // acelerar la redacción de documentos intermedios
    };
    pdf.Save(result, options);
    return result;
}

private static PdfDocument GetMergedDocument(Stream[] streams, int startIndex, int count)
{
    var pdf = new PdfDocument();
    try
    {
        for (int i = 0; i < count; ++i)
        {
            var s = streams[startIndex + i];
            pdf.Append(s);
            s.Dispose();
        }

        pdf.RemovePage(0);

        pdf.ReplaceDuplicateObjects();

        return pdf;
    }
    catch
    {
        pdf.Dispose();
        throw;
    }
}

El código anterior divide los documentos de entrada en grupos del tamaño rangeSize. Luego, el código fusiona cada grupo en documentos intermedios en paralelo. El proceso continúa hasta que el número de documentos de entrada es lo suficientemente pequeño como para realizar una simple fusión.

La solución paralela no es necesariamente más rápida que la versión de un solo subproceso. Los resultados pueden variar según la cantidad de documentos ingresados y sus tamaños. En el código de muestra, el valor óptimo del parámetro rangeSize puede ser mayor o menor. Debe comparar su aplicación para encontrar la implementación más efectiva.

Conclusión

Puede utilizar la biblioteca Docotic.Pdf para combinar documentos PDF en C# y VB.NET. Le permite fusionar archivos, secuencias o matrices de bytes. Puede fusionar archivos cifrados, formularios PDF y páginas PDF específicas. Docotic.Pdf también le ayuda a comprimir los archivos resultantes y ahorrar espacio en el disco.

Pruebe ejemplos de código del repositorio de ejemplos Docotic.Pdf en GitHub. Puede obtener una clave de licencia de evaluación y descargar la biblioteca en la página de descarga de Docotic.Pdf.