19

如何合并多个 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();
}

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

4

6 回答 6

53

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

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

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

您可以在iText in Action - 2nd Edition的第 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();
}

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

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

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

  • PdfCopyFields:将不同表单的字段放在一个表单中。可用于避免使用PdfCopy. 内存使用可能是一个问题。

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

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

于 2013-04-11T09:39:24.110 回答
9

我使用 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;
    }
}
于 2014-03-02T02:45:07.643 回答
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;
        }
    }

这不是我写的,而是做了一些修改。我不记得我在哪里找到的。合并 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;
}

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

于 2013-04-10T19:08:18.673 回答
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;
        }
    }
于 2016-10-06T13:25:31.000 回答
3

为了避免提到的内存问题,我使用文件流而不是内存流(在ITextSharp Out of memory exception merging multiple pdf中提到)来合并 pdf 文件:

        var parentDirectory = Directory.GetParent(SelectedDocuments[0].FilePath);
        var savePath = parentDirectory + "\\MergedDocument.pdf";

        using (var fs = new FileStream(savePath, FileMode.Create))
        {
            using (var document = new Document())
            {
                using (var pdfCopy = new PdfCopy(document, fs))
                {
                    document.Open();
                    for (var i = 0; i < SelectedDocuments.Count; i++)
                    {
                        using (var pdfReader = new PdfReader(SelectedDocuments[i].FilePath))
                        {
                            for (var page = 0; page < pdfReader.NumberOfPages;)
                            {
                                pdfCopy.AddPage(pdfCopy.GetImportedPage(pdfReader, ++page));
                            }
                        }
                    }
                }
            }
        }
于 2016-03-23T09:28:28.850 回答
0
****/*For Multiple PDF Print..!!*/****

<button type="button" id="btnPrintMultiplePdf" runat="server" class="btn btn-primary btn-border btn-sm"
                                                                onserverclick="btnPrintMultiplePdf_click">
                                                                <i class="fa fa-file-pdf-o"></i>Print Multiple pdf</button>

protected void btnPrintMultiplePdf_click(object sender, EventArgs e)
    {
        if (ValidateForMultiplePDF() == true)
        {
            #region Declare Temp Variables..!!
            CheckBox chkList = new CheckBox();
            HiddenField HidNo = new HiddenField();

            string Multi_fofile, Multi_listfile;
            Multi_fofile = Multi_listfile = "";
            Multi_fofile = Server.MapPath("PDFRNew");
            #endregion

            for (int i = 0; i < grdRnew.Rows.Count; i++)
            {
                #region Find Grd Controls..!!
                CheckBox Chk_One = (CheckBox)grdRnew.Rows[i].FindControl("chkOne");
                Label lbl_Year = (Label)grdRnew.Rows[i].FindControl("lblYear");
                Label lbl_No = (Label)grdRnew.Rows[i].FindControl("lblCode");
                #endregion

                if (Chk_One.Checked == true)
                {
                    HidNo .Value = llbl_No .Text.Trim()+ lbl_Year .Text;

                    if (File.Exists(Multi_fofile + "\\" + HidNo.Value.ToString() + ".pdf"))
                    {
                        #region Get Multiple Files Name And Paths..!!
                        if (Multi_listfile != "")
                        {
                            Multi_listfile = Multi_listfile + ",";
                        }
                        Multi_listfile = Multi_listfile + Multi_fofile + "\\" + HidNo.Value.ToString() + ".pdf";

                        #endregion
                    }
                }
            }

            #region For Generate Multiple Pdf..!!
            if (Multi_listfile != "")
            {
                String[] Multifiles = Multi_listfile.Split(',');
                string DestinationFile = Server.MapPath("PDFRNew") + "\\Multiple.Pdf";
                MergeFiles(DestinationFile, Multifiles);

                Response.ContentType = "pdf";
                Response.AddHeader("Content-Disposition", "attachment;filename=\"" + DestinationFile + "\"");
                Response.TransmitFile(DestinationFile);
                Response.End();
            }
            else
            {

            }
            #endregion
        }
    }

    private void MergeFiles(string DestinationFile, string[] SourceFiles)
    {
        try
        {
            int f = 0;
            /**we create a reader for a certain Document**/
            PdfReader reader = new PdfReader(SourceFiles[f]);
            /**we retrieve the total number of pages**/
            int n = reader.NumberOfPages;
            /**Console.WriteLine("There are " + n + " pages in the original file.")**/
            /**Step 1: creation of a document-object**/
            Document document = new Document(reader.GetPageSizeWithRotation(1));
            /**Step 2: we create a writer that listens to the Document**/
            PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(DestinationFile, FileMode.Create));
            /**Step 3: we open the Document**/
            document.Open();
            PdfContentByte cb = writer.DirectContent;
            PdfImportedPage page;
            int rotation;
            /**Step 4: We Add Content**/
            while (f < SourceFiles.Length)
            {
                int i = 0;
                while (i < n)
                {
                    i++;
                    document.SetPageSize(reader.GetPageSizeWithRotation(i));
                    document.NewPage();
                    page = writer.GetImportedPage(reader, i);
                    rotation = reader.GetPageRotation(i);
                    if (rotation == 90 || rotation == 270)
                    {
                        cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height);
                    }
                    else
                    {
                        cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
                    }
                    /**Console.WriteLine("Processed page " + i)**/
                }
                f++;
                if (f < SourceFiles.Length)
                {
                    reader = new PdfReader(SourceFiles[f]);
                    /**we retrieve the total number of pages**/
                    n = reader.NumberOfPages;
                    /**Console.WriteLine("There are"+n+"pages in the original file.")**/
                }
            }
            /**Step 5: we Close the Document**/
            document.Close();
        }
        catch (Exception e)
        {
            string strOb = e.Message;
        }
    }

    private bool ValidateForMultiplePDF()
    {
        bool chkList = false;

        foreach (GridViewRow gvr in grdRnew.Rows)
        {
            CheckBox Chk_One = (CheckBox)gvr.FindControl("ChkSelectOne");
            if (Chk_One.Checked == true)
            {
                chkList = true;
            }
        }
        if (chkList == false)
        {
            divStatusMsg.Style.Add("display", "");
            divStatusMsg.Attributes.Add("class", "alert alert-danger alert-dismissable");
            divStatusMsg.InnerText = "ERROR !!...Please Check At Least On CheckBox.";
            grdRnew.Focus();
            set_timeout();
            return false;
        }
        return true;
    }
于 2018-09-27T11:12:55.497 回答