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

如何通过ItextSharp合并多个pdf文件(在运行时生成),然后打印出来。

我发现了以下链接,但该方法需要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文件来打印它

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

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

  2. 您实际上想要将源文档中的页面整合到新文档中,但希望新文档能够pipe理通用格式,而不需要关注原始文档中的交互function(注释…)(或者甚至想要摆脱)。 在这种情况下,您应该使用基于PdfWriter类的解决scheme。

您可以在iText in Action – 2nd Edition的 第6章 (特别是第6.4节)中find详细信息。 Java示例代码可以在这里和C#的ified版本在这里访问 。

使用PdfCopy的简单示例是Concatenate.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需要更多的内存和CPU。

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

我用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; } } 

这是我从一个旧项目中抽出的一些代码。 这是一个Web应用程序,但我使用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; } } 

我没有写这个,但做了一些修改。 我不记得我在哪里find它。 合并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时是有用的。

使用iTextSharp-LGPL 4.1.6testing:

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

为了避免提到的内存问题,我使用文件stream而不是内存stream(在ITextSharp中提到的内存不足例外合并多个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)); } } } } } }