이 페이지에는 자동 번역된 텍스트가 포함될 수 있습니다.

C# 및 VB.NET에서 PDF 문서 병합

기업에서는 문서 보관을 위해 PDF 파일을 병합하는 경우가 많습니다. PDF 병합은 간단한 작업처럼 들리지만 여기에는 많은 함정이 있습니다. 양식 필드, 책갈피, 레이어 및 기타 PDF 개체를 적절하게 결합해야 합니다. 또한 압축된 출력 파일을 얻으려면 중복 개체를 피해야 합니다.

Docotic.Pdf 라이브러리는 모든 병합의 미묘한 차이를 처리합니다. 단 몇 줄의 C# 또는 VB.NET 코드로 PDF 문서를 결합할 수 있습니다.

PDF 문서 병합

Docotic.Pdf는 무료 및 유료 라이센스와 함께 제공됩니다. Docotic.Pdf 다운로드 페이지에서 라이브러리를 다운로드하고 평가판 라이센스 키를 얻을 수 있습니다.

Docotic.Pdf 라이브러리 9.4.17467-dev 회귀 테스트 14,760건의 테스트 통과 총 NuGet 다운로드 4,415,970

PDF 병합 기본 사항

PdfDocument.Append 메서드를 사용하면 파일, 스트림 또는 바이트 배열에서 PDF 문서를 추가할 수 있습니다. 보호된 파일을 추가하고 양식 필드를 병합하는 옵션도 있습니다.

두 개의 PDF 파일 결합

이 샘플 코드는 C#에서 PDF 파일을 병합하는 방법을 보여줍니다.

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

GitHub의 두 개의 PDF 문서 병합 코드 샘플을 사용해 보세요.

PDF 스트림 결합

파일 경로 대신 스트림을 사용하여 작업하도록 이전 예제를 쉽게 적용할 수 있습니다. 스트림 병합을 위한 도우미 메서드는 다음과 같습니다.

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

여러 PDF 파일 결합

여러 PDF 파일을 추가하려면 Append 메서드를 반복적으로 호출할 수 있습니다.

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

// PdfDocument() 호출로 추가된 빈 페이지 제거
pdf.RemovePage(0);

pdf.Save(pathToFile);

암호화된 PDF 파일 결합

암호화된 문서를 병합하기 위한 Append 오버로드가 있습니다.

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

자세한 내용은 C# 및 VB.NET에서 PDF 문서 해독 문서에서 확인할 수 있습니다.

PDF 양식 결합

PDF 문서의 모든 양식 필드에는 고유한 이름이 있어야 합니다. 병합할 문서에 동일한 이름의 필드가 포함되어 있으면 문제가 발생할 수 있습니다. Docotic.Pdf는 충돌하는 양식 제어에 대해 다음과 같은 병합 전략을 제공합니다.

  • 추가된 컨트롤이 기존 컨트롤과 충돌하는 경우 이름 바꾸기
  • 추가된 컨트롤을 기존 컨트롤에 병합
  • 추가된 컨트롤을 평면화
  • 컨트롤을 추가하지 마세요
  • 컨트롤을 있는 그대로 추가

기본적으로 라이브러리는 충돌 시 추가된 컨트롤의 이름을 바꿉니다. 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");

CopyAsKids 모드를 사용하면 라이브러리가 충돌하는 컨트롤을 병합하고 동기화합니다. 즉, 하나의 컨트롤을 변경하면 두 번째 컨트롤도 동일한 값을 갖게 됩니다.

병합된 PDF 파일 줄이기

PDF 문서에는 글꼴이나 이미지와 같은 동일한 개체가 포함될 수 있습니다. 이러한 문서를 병합하면 결과 문서에는 동일한 개체의 복사본이 포함됩니다. PdfDocument.ReplaceDuplicateObjects() 메서드를 사용하여 병합 결과를 최적화합니다.

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

pdf.ReplaceDuplicateObjects();

pdf.Save("merged.pdf");

출력 파일 크기를 더욱 줄일 수 있습니다. 예를 들어, 사용하지 않는 글꼴 문자를 제거하거나 이미지를 압축할 수 있습니다. C# 및 VB.NET에서 PDF 문서 압축 문서에서 지원되는 압축 옵션에 대해 읽어보세요.

PDF 병합 사용자 정의

Docotic.Pdf는 PDF 페이지를 추출, 재정렬 또는 제거하는 방법을 제공합니다. 이를 Append 메소드와 함께 사용하여 사용자 정의 PDF 병합 작업을 구현할 수 있습니다.

특정 PDF 페이지 추가

Docotic.Pdf를 사용하면 PDF 문서의 일부를 병합할 수도 있습니다. 이를 수행하는 방법에는 여러 가지가 있습니다. 예를 들어, 추가된 PDF 문서를 분할하고 추출된 페이지를 추가할 수 있습니다. 다음 C# 도우미는 선택한 페이지를 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);
}

또는 전체 PDF 문서를 추가하고 불필요한 페이지를 제거할 수 있습니다. 다음 코드 샘플은 second.pdf의 처음 두 페이지를 추가합니다.

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

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

pdf.Save(pathToFile);

또 다른 솔루션은 PDF 임포지션과 관련이 있습니다. 이에 대한 내용은 해당 섹션에서 읽어보실 수 있습니다.

PDF 앞에 추가

Append 메소드는 항상 현재 문서의 끝에 페이지를 추가합니다. PDF 파일을 다른 순서로 병합하는 방법은 무엇입니까? 때로는 Append 호출의 순서를 변경할 수 있습니다. 즉,

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

대신

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

를 사용하세요.

또는 병합 후 페이지 순서를 변경할 수 있습니다. 이 C# 코드는 추가된 PDF 문서를 시작 부분으로 이동합니다.

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

PDF 페이지 재정렬을 위한 관련 코드 샘플:

PDF 임포징

Docotic.Pdf를 사용하면 여러 PDF 페이지를 단일 페이지에 결합할 수 있습니다. PdfDocument.CreateXObject(PdfPage) 메서드를 사용하여 기존 페이지를 기반으로 PdfXObject 개체를 만듭니다. 그런 다음 원하는 비율로 이 개체를 그립니다. 샘플 코드:

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

GitHub에서 관련 페이지에서 XObject 만들기 샘플 프로젝트를 테스트합니다.

첨부 파일로 병합

때로는 PDF 파일을 다른 파일에 첨부 파일로 포함해야 할 수도 있습니다. 그것도 가능합니다. 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");

GitHub의 PDF 첨부 파일 그룹에서 관련 코드 샘플을 찾을 수 있습니다.

병렬 스레드로 병합

많은 PDF 파일을 병합할 때 코드를 병렬화하는 것이 가능합니다. PdfDocument 클래스는 스레드로부터 안전하지 않습니다. 따라서 서로 다른 스레드에서 별도의 PdfDocument 개체를 사용해야 합니다. 자세한 내용은 PDF 문서를 병렬 스레드로 병합 코드 샘플을 참조하세요.

이 코드는 PDF 스트림을 병렬로 결합하는 방법을 보여줍니다.

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 // 중간 문서 작성 속도 향상
    };
    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;
    }
}

위 코드는 입력 문서를 rangeSize 크기의 그룹으로 분할합니다. 그런 다음 코드는 각 그룹을 중간 문서로 병렬로 병합합니다. 입력 문서의 수가 간단한 병합을 할 수 있을 만큼 작아질 때까지 프로세스가 계속됩니다.

병렬 솔루션이 반드시 단일 스레드 버전보다 빠르지는 않습니다. 입력 문서의 수와 크기에 따라 결과가 달라질 수 있습니다. 샘플 코드에서 rangeSize 매개변수의 최적 값은 더 크거나 작을 수 있습니다. 가장 효과적인 구현을 찾으려면 애플리케이션을 벤치마킹해야 합니다.

결론

Docotic.Pdf 라이브러리를 사용하여 C# 및 VB.NET의 PDF 문서를 결합할 수 있습니다. 파일, 스트림 또는 바이트 배열을 병합할 수 있습니다. 암호화된 파일, PDF 양식, 특정 PDF 페이지를 병합할 수 있습니다. Docotic.Pdf는 또한 결과 파일을 압축하고 디스크 공간을 절약하는 데 도움이 됩니다.

GitHub의 Docotic.Pdf 샘플 저장소에서 코드 샘플을 사용해 보세요. Docotic.Pdf 다운로드 페이지에서 평가판 라이센스 키를 받고 라이브러리를 다운로드할 수 있습니다.