简体   繁体   English

使用 ITextSharp(旧版本)将多个文件合并到 pdf

[英]Merge multiple files into a pdf with ITextSharp (Old version)

First of all, sorry for the low effort question.. I have used these questions as a reference:首先,很抱歉这个低努力的问题。我用这些问题作为参考:

Merging multiple PDFs using iTextSharp in c#.net 在 c#.net 中使用 iTextSharp 合并多个 PDF
C# iTextSharp Merge multiple pdf via byte array C# iTextSharp 通过字节数组合并多个 pdf

My requirements are a bit different.我的要求有点不同。

I get an input of multiple files, either images and/or pdf's, and I need to merge them together into 1 pdf.我得到多个文件的输入,图像和/或 pdf,我需要将它们合并到 1 pdf 中。
Each image gets it own page.每个图像都有自己的页面。 So if you have 2 images, you get a pdf with 1 image on each page.因此,如果您有 2 张图片,您将获得 pdf,每页有 1 张图片。 If you have 1 pdf with 2 pages, 1 image and another pdf with 3 images, the resulting PDF will have 6 pages.如果您有 1 个 pdf 有 2 个页面,1 个图像和另一个 pdf 有 3 个图像,生成的 PDF 将有 6 个页面。

Currently the code I use with IText7 (The newer version) is as follows:目前我与 IText7 (较新版本)一起使用的代码如下:

using iText.IO.Image;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using System.Collections.Generic;
using System.IO;

namespace Example
{
    public class ITextPdfCreator : IPdfCreator
    {
        public MemoryStream Create(IEnumerable<(string ContentType, byte[] Content)> blobs)
        {
            using (var memoryStream = new MemoryStream())
            {
                using (var writer = new PdfWriter(memoryStream))
                {
                    var pdf = new PdfDocument(writer);
                    var document = new Document(pdf);
                    var firstIteration = true;

                    foreach (var blob in blobs)
                    {
                        if (!firstIteration)
                        {
                            document.Add(new AreaBreak(iText.Layout.Properties.AreaBreakType.NEXT_PAGE));
                        }

                        if (blob.ContentType.StartsWith("image/"))
                        {
                            var content = new Image(ImageDataFactory.Create(blob.Content));
                            document.Add(content);
                        }
                        else if (blob.ContentType.StartsWith("application/pdf"))
                        {
                            Stream stream = new MemoryStream(blob.Content);
                            var d = new PdfDocument(new PdfReader(stream));
                            d.CopyPagesTo(1, d.GetNumberOfPages(), pdf, pdf.GetNumberOfPages() + 1);
                        }

                        firstIteration = false;
                    }
                    document.Close();
                }

                return memoryStream;
            }
        }
    }
}

I was wondering if anyone had the know-how to implement this with https://github.com/VahidN/iTextSharp.LGPLv2.Core .我想知道是否有人知道如何使用https://github.com/VahidN/iTextSharp.LGPLv2.Core来实现它。 Previously mentioned questions merge multiple pdf's together, but I need to merge images as well.前面提到的问题将多个 pdf 合并在一起,但我也需要合并图像。

In the end, my code needs to run on .NET 5.0 and windows and linux.最后,我的代码需要在 .NET 5.0 和 windows 和 linux 上运行。 I believe that this lib supports it:)我相信这个库支持它:)

If anyone has any clue, that'd be amazing, If not.如果有人有任何线索,那将是惊人的,如果没有。 feel free to be annoyed at me for a low effort question.. When I figure it out myself I will post an update!对于一个不费吹灰之力的问题,请随时对我生气。当我自己弄清楚时,我会发布更新!

I have found a solution!我找到了解决方案!

My code is as follows:我的代码如下:

using iTextSharp.text;
using iTextSharp.text.pdf;
using System;
using System.Collections.Generic;
using System.IO;

public class ITextSharpPdfMerger
{
    private const float _imageLeftMargin = 10f;
    private const float _imageRightMargin = 10f;
    private const float _imageBottomMargin = 30f;
    private const float _imageTopMargin = 30f;

    // https://github.com/VahidN/iTextSharp.LGPLv2.Core
    // https://stackoverflow.com/a/6056801/3013479
    public byte[] Create(IEnumerable<(string ContentType, byte[] Content)> blobs)
    {
        Document document = null;
        PdfCopy copy = null;

        using (var stream = new MemoryStream())
        {

            try
            {
                document = new Document();
                copy = new PdfCopy(document, stream);

                document.Open();

                foreach (var blob in blobs)
                {
                    if (blob.ContentType.StartsWith("image/"))
                    {
                        AddImage(copy, blob.Content);
                    }
                    else if (blob.ContentType == "application/pdf")
                    {
                        AddPdf(copy, blob.Content);
                    }
                    else
                    {
                        throw new ArgumentException($"Blob with ContentType {blob.ContentType} is not supported for merging.");
                    }
                }
            }
            finally
            {
                document?.Close();
                copy?.Close();
            }

            return stream.ToArray();
        }
    }

    private static void AddPdf(PdfCopy copy, byte[] content)
    {
        PdfReader reader = null;
        try
        {
            reader = new PdfReader(content);

            // Grab each page from the PDF and copy it
            for (int i = 1; i <= reader.NumberOfPages; i++)
            {
                var page = copy.GetImportedPage(reader, i);
                copy.AddPage(page);
            }

            // A PDF can have a form; we copy it into the resulting pdf.
            // Example: https://web.archive.org/web/20210322125650/https://www.windjack.com/PDFSamples/ListPrograming_Part1_AcroForm.pdf 
            var form = reader.AcroForm;
            if (form != null)
            {
                copy.CopyAcroForm(reader);
            }

        }
        finally
        {
            reader?.Close();
        }
    }

    private static void AddImage(PdfCopy copy, byte[] content)
    {
        // We have a little workaround to add images because we use PdfCopy which is only useful for COPYING and doesn't work for adding pages manually.
        // So we create a new PDF in memory containing the image, and then we copy that PDF into the resulting PDF.
        // https://stackoverflow.com/a/26111677/3013479
        Document document = null;
        PdfWriter writer = null;
        PdfReader reader = null;
        using (var stream = new MemoryStream())
        {
            try
            {
                document = new Document();
                writer = PdfWriter.GetInstance(document, stream);

                document.Open();
                if (!document.NewPage())
                {
                    throw new Exception("New page could not be created");
                }

                var image = Image.GetInstance(content);

                // Make the image fit on the page
                // https://stackoverflow.com/q/4932187/3013479
                image.Alignment = Element.ALIGN_MIDDLE;
                var pageWidth = copy.PageSize.Width - (_imageLeftMargin + _imageRightMargin);
                var pageHeight = copy.PageSize.Height - (_imageBottomMargin + _imageTopMargin);
                image.ScaleToFit(pageWidth, pageHeight);

                if (!document.Add(image))
                {
                    throw new Exception("Unable to add image to page");
                }

                // These are required for the PdfReader instantation to succeed
                document.Close();
                writer.Close();

                reader = new PdfReader(stream.ToArray());

                copy.AddPage(copy.GetImportedPage(reader, 1));
            }
            finally
            {
                document?.Close();
                reader?.Close();
                writer?.Close();
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM