Questa pagina può contenere testo tradotto automaticamente.

Unire documenti PDF in C# e VB.NET

Le aziende spesso uniscono file PDF per l'archiviazione dei documenti. Anche se l'unione di PDF sembra un compito semplice, qui ci sono molte insidie. Devi combinare correttamente campi modulo, segnalibri, livelli e altri oggetti PDF. Devi anche evitare oggetti duplicati per ottenere un file di output compatto.

La libreria Docotic.Pdf gestisce tutte le sfumature dell'unione. Ti consente di combinare documenti PDF in poche righe di codice C# o VB.NET.

Unire documenti PDF

Docotic.Pdf include licenze gratuite e a pagamento. Ottieni la libreria e una chiave di licenza gratuita a tempo limitato nella pagina Scarica la libreria PDF C# .NET.

Nozioni di base sull'unione di PDF

I metodi PdfDocument.Append consentono di accodare documenti PDF da file, flussi o array di byte. Sono inoltre disponibili opzioni per accodare file protetti e per unire campi modulo.

Unire due file PDF

Questo esempio di codice mostra come unire file PDF in C#:

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

Prova l'esempio di codice Unisci due documenti PDF su GitHub.

Unire flussi PDF

È facile adattare l'esempio precedente per lavorare con i flussi invece che con i percorsi dei file. Ecco il metodo helper per unire i flussi:

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

Unire più file PDF

Puoi chiamare ripetutamente il metodo Append per accodare più file PDF:

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

// Rimuovi la pagina vuota aggiunta dalla chiamata PdfDocument()
pdf.RemovePage(0);

pdf.Save(pathToFile);

Unire file PDF crittografati

Esistono overload di Append per unire documenti crittografati:

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

Puoi trovare ulteriori informazioni nell'articolo Decifrare documenti PDF in C# e VB.NET.

Unire moduli PDF

Ogni campo modulo in un documento PDF deve avere un nome univoco. Questo può causare un problema quando i documenti da unire contengono campi con gli stessi nomi. Docotic.Pdf offre le seguenti strategie di unione per controlli modulo in conflitto:

  • Rinominare i controlli accodati quando sono in conflitto con i controlli esistenti
  • Unire i controlli accodati ai controlli esistenti
  • Appiattire i controlli accodati
  • Non accodare alcun controllo
  • Accodare i controlli così come sono

Per impostazione predefinita, la libreria rinomina i controlli accodati in caso di conflitto. Puoi scegliere una strategia alternativa con la classe 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 la modalità CopyAsKids, la libreria unisce e sincronizza i controlli in conflitto. Cioè, quando modifichi un controllo, il secondo avrà lo stesso valore.

Ridurre il file PDF unito

I documenti PDF possono contenere oggetti identici, come font o immagini. Quando unisci questi documenti, il documento risultante conterrà copie degli stessi oggetti. Usa il metodo PdfDocument.ReplaceDuplicateObjects() per ottimizzare il risultato dell'unione:

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

pdf.ReplaceDuplicateObjects();

pdf.Save("merged.pdf");

Puoi ridurre ulteriormente la dimensione del file di output. Ad esempio, puoi rimuovere i glifi dei font non usati o comprimere le immagini. Leggi le opzioni di compressione supportate nell'articolo Comprimi documenti PDF in C# e VB.NET.

Personalizzare l'unione dei PDF

Docotic.Pdf offre metodi per estrarre, riordinare o rimuovere pagine PDF. Puoi usarli con il metodo Append per implementare attività personalizzate di unione PDF.

Aggiungere pagine PDF specifiche

Docotic.Pdf consente anche di unire una parte di un documento PDF. Esistono diversi modi per farlo. Ad esempio, puoi dividere un documento PDF aggiunto e accodare le pagine estratte. Il seguente helper C# accoda le pagine selezionate a 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);
}

Oppure puoi accodare un intero documento PDF e rimuovere le pagine non necessarie. Il seguente esempio di codice accoda le prime due pagine di second.pdf:

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

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

pdf.Save(pathToFile);

Un'altra soluzione riguarda l'imposizione PDF. Puoi leggere l'argomento nella sezione corrispondente.

Anteporre PDF

I metodi Append accodano sempre le pagine alla fine del documento corrente. Come unire file PDF in ordine diverso? A volte puoi cambiare l'ordine delle chiamate Append. Cioè, usa

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

al posto di

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

Oppure puoi riordinare le pagine dopo l'unione. Questo codice C# sposta il documento PDF accodato all'inizio:

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);

Per ulteriori informazioni sul riordino delle pagine PDF, leggi:

Imposizione PDF

Docotic.Pdf consente di combinare più pagine PDF in una singola pagina. Usa il metodo PdfDocument.CreateXObject(PdfPage) per creare un oggetto PdfXObject basato su una pagina esistente. Quindi, disegna questo oggetto con la scala desiderata. Esempio di codice:

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");

Prova il progetto di esempio correlato Crea XObject dalla pagina su GitHub.

Unire come allegato

A volte potresti dover incorporare un file PDF in un altro come allegato. È possibile anche questo. Puoi inoltre aggiungere collegamenti al file incorporato nelle pagine 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");

Puoi trovare esempi di codice correlati nel gruppo allegati PDF su GitHub.

Unire in thread paralleli

Quando si uniscono molti file PDF, è possibile parallelizzare il codice. La classe PdfDocument non è thread-safe. Quindi, dobbiamo usare oggetti PdfDocument separati in thread diversi. Guarda l'esempio di codice Unisci documenti PDF in thread paralleli per maggiori dettagli.

Questo codice mostra come combinare flussi PDF in parallelo:

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 // accelera la scrittura dei documenti intermedi
    };
    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;
    }
}

Il codice sopra divide i documenti di input in gruppi della dimensione rangeSize. Poi, il codice unisce ciascun gruppo in documenti intermedi in parallelo. Il processo continua fino a quando il numero di documenti di input è abbastanza piccolo per l'unione semplice.

La soluzione parallela non è necessariamente più veloce della versione a thread singolo. I risultati possono variare in base al numero di documenti di input e alle loro dimensioni. Nel codice di esempio, il valore ottimale del parametro rangeSize potrebbe essere maggiore o minore. Dovresti eseguire un benchmark della tua applicazione per trovare l'implementazione più efficace.

Conclusione

Puoi usare la libreria Docotic.Pdf per unire documenti PDF in C# e VB.NET. Consente di unire file, flussi o array di byte. Puoi unire file crittografati, moduli PDF, pagine PDF specifiche. Docotic.Pdf aiuta anche a comprimere i file risultanti e a risparmiare spazio su disco.

Prova gli esempi di codice dal repository di esempi di Docotic.Pdf su GitHub. Puoi ottenere una chiave di licenza di valutazione e scaricare la libreria dalla pagina di download di Docotic.Pdf.