如何合并多个pdf文件(在运行时生成)?

Any*_*are 18 c# pdf asp.net rdlc itextsharp

如何合并多个pdf文件(在运行时生成)ItextSharp然后打印它们.

我找到了以下链接,但该方法需要pdf名称考虑到存储的pdf文件,这不是我的情况.


我有多个报告我会pdf files通过这种方法将它们转换为:

private void AddReportToResponse(LocalReport followsReport)
{
    string mimeType;
    string encoding;
    string extension;
    string[] streams = new string[100];
    Warning[] warnings = new Warning[100];
    byte[] pdfStream = followsReport.Render("PDF", "", out mimeType, out encoding, out extension, out streams, out warnings);
  //Response.Clear();
  //Response.ContentType = mimeType;
  //Response.AddHeader("content-disposition", "attachment; filename=Application." + extension);
  //Response.BinaryWrite(pdfStream);
  //Response.End();
}
Run Code Online (Sandbox Code Playgroud)

现在我想将所有生成的文件(Bytes)合并到一个pdf文件中进行打印

mkl*_*mkl 48

如果要使用iText(Sharp)合并源文档,有两种基本情况:

  1. 您确实希望合并文档,以原始格式获取页面,尽可能多地传输内容和交互式注释.在这种情况下,您应该使用基于Pdf*Copy*类族成员的解决方案.

  2. 您实际上想要将源文档中的页面集成到新文档中,但希望新文档管理一般格式,而不关心原始文档中的交互功能(注释...)(甚至想要摆脱他们).在这种情况下,您应该使用基于PdfWriter类的解决方案.

您可以在iText in Action - 第2版的第6章(特别是第6.4节)中找到详细信息.Java的示例代码可以访问这里和C#"指明分数版本在这里.

使用的简单示例PdfCopyConcatenate.java/Concatenate.cs.代码的核心是:

byte[] mergedPdf = null;
using (MemoryStream ms = new MemoryStream())
{
    using (Document document = new Document())
    {
        using (PdfCopy copy = new PdfCopy(document, ms))
        {
            document.Open();

            for (int i = 0; i < pdf.Count; ++i)
            {
                PdfReader reader = new PdfReader(pdf[i]);
                // loop over the pages in that document
                int n = reader.NumberOfPages;
                for (int page = 0; page < n; )
                {
                    copy.AddPage(copy.GetImportedPage(reader, ++page));
                }
            }
        }
    }
    mergedPdf = ms.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

这里pdf可以定义为List<byte[]>直接包含源文档(适用于合并中间内存文档的用例)或List<String>包含源文档文件的名称(如果从磁盘合并文档,则适用).

引用章节末尾的概述总结了所提到的类的用法:

  • PdfCopy:从一个或多个现有PDF文档复制页面.主要缺点:PdfCopy未检测到冗余内容,并且在连接表单时失败.

  • PdfCopyFields:将不同形式的字段放在一个表单中.可以用来避免在使用连接表单时遇到表单字段遇到的问题PdfCopy.内存使用可能是一个问题.

  • PdfSmartCopy:从一个或多个现有PDF文档复制页面.PdfSmartCopy能够检测冗余内容,但它需要更多的内存和CPU PdfCopy.

  • PdfWriter:从头开始生成PDF文档.可以从其他PDF文档导入页面.主要缺点是导入页面的所有交互功能(注释,书签,字段等)在此过程中都会丢失.

  • @MikeTeeVee*你缺少`document.Close()`* - 不,`using(Document document = new Document())`隐式关闭文件.但是,如果你需要在`using`的结束括号之前获取内存流内容,你确实需要显式关闭. (2认同)

Saj*_*ake 8

我使用iTextsharp和c#来组合pdf文件.这是我使用的代码.

string[] lstFiles=new string[3];
    lstFiles[0]=@"C:/pdf/1.pdf";
    lstFiles[1]=@"C:/pdf/2.pdf";
    lstFiles[2]=@"C:/pdf/3.pdf";

    PdfReader reader = null;
    Document sourceDocument = null;
    PdfCopy pdfCopyProvider = null;
    PdfImportedPage importedPage;
    string outputPdfPath=@"C:/pdf/new.pdf";


    sourceDocument = new Document();
    pdfCopyProvider = new PdfCopy(sourceDocument, new System.IO.FileStream(outputPdfPath, System.IO.FileMode.Create));

    //Open the output file
    sourceDocument.Open();

    try
    {
        //Loop through the files list
        for (int f = 0; f < lstFiles.Length-1; f++)
        {
            int pages =get_pageCcount(lstFiles[f]);

            reader = new PdfReader(lstFiles[f]);
            //Add pages of current file
            for (int i = 1; i <= pages; i++)
            {
                importedPage = pdfCopyProvider.GetImportedPage(reader, i);
                pdfCopyProvider.AddPage(importedPage);
            }

            reader.Close();
         }
        //At the end save the output file
        sourceDocument.Close();
    }
    catch (Exception ex)
    {
        throw ex;
    }


private int get_pageCcount(string file)
{
    using (StreamReader sr = new StreamReader(File.OpenRead(file)))
    {
        Regex regex = new Regex(@"/Type\s*/Page[^s]");
        MatchCollection matches = regex.Matches(sr.ReadToEnd());

        return matches.Count;
    }
}
Run Code Online (Sandbox Code Playgroud)


DSl*_*gle 5

这是我从一个旧项目中提取的一些代码。这是一个网络应用程序,但我使用 iTextSharp 合并 pdf 文件然后打印它们。

public static class PdfMerger
    {
        /// <summary>
        /// Merge pdf files.
        /// </summary>
        /// <param name="sourceFiles">PDF files being merged.</param>
        /// <returns></returns>
        public static byte[] MergeFiles(List<Stream> sourceFiles)
        {
            Document document = new Document();
            MemoryStream output = new MemoryStream();

            try
            {
                // Initialize pdf writer
                PdfWriter writer = PdfWriter.GetInstance(document, output);
                writer.PageEvent = new PdfPageEvents();

                // Open document to write
                document.Open();
                PdfContentByte content = writer.DirectContent;

                // Iterate through all pdf documents
                for (int fileCounter = 0; fileCounter < sourceFiles.Count; fileCounter++)
                {
                    // Create pdf reader
                    PdfReader reader = new PdfReader(sourceFiles[fileCounter]);
                    int numberOfPages = reader.NumberOfPages;

                    // Iterate through all pages
                    for (int currentPageIndex = 1; currentPageIndex <=
                                        numberOfPages; currentPageIndex++)
                    {
                        // Determine page size for the current page
                        document.SetPageSize(
                            reader.GetPageSizeWithRotation(currentPageIndex));

                        // Create page
                        document.NewPage();
                        PdfImportedPage importedPage =
                            writer.GetImportedPage(reader, currentPageIndex);


                        // Determine page orientation
                        int pageOrientation = reader.GetPageRotation(currentPageIndex);
                        if ((pageOrientation == 90) || (pageOrientation == 270))
                        {
                            content.AddTemplate(importedPage, 0, -1f, 1f, 0, 0,
                                reader.GetPageSizeWithRotation(currentPageIndex).Height);
                        }
                        else
                        {
                            content.AddTemplate(importedPage, 1f, 0, 0, 1f, 0, 0);
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                throw new Exception("There has an unexpected exception" +
                        " occured during the pdf merging process.", exception);
            }
            finally
            {
                document.Close();
            }
            return output.GetBuffer();
        }
    }



    /// <summary>
    /// Implements custom page events.
    /// </summary>
    internal class PdfPageEvents : IPdfPageEvent
    {
        #region members
        private BaseFont _baseFont = null;
        private PdfContentByte _content;
        #endregion

        #region IPdfPageEvent Members
        public void OnOpenDocument(PdfWriter writer, Document document)
        {
            _baseFont = BaseFont.CreateFont(BaseFont.HELVETICA,
                                BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
            _content = writer.DirectContent;
        }

        public void OnStartPage(PdfWriter writer, Document document)
        { }

        public void OnEndPage(PdfWriter writer, Document document)
        { }

        public void OnCloseDocument(PdfWriter writer, Document document)
        { }

        public void OnParagraph(PdfWriter writer,
                    Document document, float paragraphPosition)
        { }

        public void OnParagraphEnd(PdfWriter writer,
                    Document document, float paragraphPosition)
        { }

        public void OnChapter(PdfWriter writer, Document document,
                                float paragraphPosition, Paragraph title)
        { }

        public void OnChapterEnd(PdfWriter writer,
                    Document document, float paragraphPosition)
        { }

        public void OnSection(PdfWriter writer, Document document,
                    float paragraphPosition, int depth, Paragraph title)
        { }

        public void OnSectionEnd(PdfWriter writer,
                    Document document, float paragraphPosition)
        { }

        public void OnGenericTag(PdfWriter writer, Document document,
                                    Rectangle rect, string text)
        { }
        #endregion

        private float GetCenterTextPosition(string text, PdfWriter writer)
        {
            return writer.PageSize.Width / 2 - _baseFont.GetWidthPoint(text, 8) / 2;
        }
    }
Run Code Online (Sandbox Code Playgroud)

我没有写这个,但做了一些修改。我不记得我在哪里找到的。合并 PDF 后,我将调用此方法插入 javascript 以在打开 PDF 时打开打印对话框。如果您将 bSilent 更改为 true,则它应该以静默方式打印到默认打印机。

public Stream addPrintJStoPDF(Stream thePDF)
{
    MemoryStream outPutStream = null;
    PRStream finalStream = null;
    PdfDictionary page = null;
    string content = null;

    //Open the stream with iTextSharp
    var reader = new PdfReader(thePDF);

    outPutStream = new MemoryStream(finalStream.GetBytes());
    var stamper = new PdfStamper(reader, (MemoryStream)outPutStream);
    var jsText = "var res = app.setTimeOut('this.print({bUI: true, bSilent: false, bShrinkToFit: false});', 200);";
    //Add the javascript to the PDF
    stamper.JavaScript = jsText;

    stamper.FormFlattening = true;
    stamper.Writer.CloseStream = false;
    stamper.Close();

    //Set the stream to the beginning
    outPutStream.Position = 0;

    return outPutStream;
}
Run Code Online (Sandbox Code Playgroud)

不确定上面的代码写得有多好,因为我是从其他地方提取的,而且我根本没有使用 iTextSharp 进行过深入的工作,但我知道它确实可以合并我在运行时生成的 PDF。

  • 请不要使用这种合并例程,除非您有非常具体的要求迫使您这样做。当您使用 `PdfWriter` 合并源 PDF 时,交互功能(表单和其他注释)会丢失。此外,生成的 PDF 在内部包含一个不必要的页面信息包装器,当多次迭代时,可能会导致 PDF 查看器在尝试显示 PDF 时失败。 (2认同)

Nin*_*ina 5

使用iTextSharp-LGPL 4.1.6测试:

    public static byte[] ConcatenatePdfs(IEnumerable<byte[]> documents)
    {
        using (var ms = new MemoryStream())
        {
            var outputDocument = new Document();
            var writer = new PdfCopy(outputDocument, ms);
            outputDocument.Open();

            foreach (var doc in documents)
            {
                var reader = new PdfReader(doc);
                for (var i = 1; i <= reader.NumberOfPages; i++)
                {
                    writer.AddPage(writer.GetImportedPage(reader, i));
                }
                writer.FreeReader(reader);
                reader.Close();
            }

            writer.Close();
            outputDocument.Close();
            var allPagesContent = ms.GetBuffer();
            ms.Flush();

            return allPagesContent;
        }
    }
Run Code Online (Sandbox Code Playgroud)