c# asp.net pdf itextsharp rdlc

c# - ¿Cómo fusionar varios archivos pdf(generados en tiempo de ejecución)?



asp.net itextsharp (6)

Aquí hay un código que saqué de un viejo proyecto que tenía. Era una aplicación web, pero estaba usando iTextSharp para combinar archivos PDF y luego imprimirlos.

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

No escribí esto, pero hice algunas modificaciones. No recuerdo dónde lo encontré. Después de fusionar los PDF, llamaría a este método para insertar javascript para abrir el cuadro de diálogo de impresión cuando se abre el PDF. Si cambia bSilent a verdadero, entonces debería imprimir en silencio en su impresora predeterminada.

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

No estoy seguro de qué tan bien está escrito el código anterior ya que lo extraje de otro lugar y no he trabajado en profundidad con iTextSharp, pero sí sé que funcionó en la combinación de archivos PDF que estaba generando en el tiempo de ejecución.

Cómo fusionar varios archivos PDF (generados en tiempo de ejecución) a través de ItextSharp luego imprimirlos.

Encontré el siguiente link pero ese método requiere los nombres de los archivos PDF, ya que los archivos PDF están almacenados y este no es mi caso.

Tengo varios informes, los convertiré a pdf files través de este método:

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

Ahora quiero fusionar todos los archivos generados ( Bytes ) en un archivo pdf para imprimirlo


Para evitar los problemas de memoria mencionados, usé la secuencia de archivos en lugar de la secuencia de memoria (mencionada en ITextSharp Excepción de memoria fuera de la combinación de varios pdf ) para combinar archivos 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)); } } } } } }


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


Si desea combinar documentos de origen utilizando iText (Sharp), hay dos situaciones básicas:

  1. Realmente desea fusionar los documentos, adquirir las páginas en su formato original, transferir la mayor parte de su contenido y sus anotaciones interactivas como sea posible. En este caso, debe utilizar una solución basada en un miembro de la familia de clases Pdf*Copy* .

  2. Realmente desea integrar las páginas de los documentos de origen en un nuevo documento, pero desea que el nuevo documento rija el formato general y no cuide las funciones interactivas (anotaciones ...) en los documentos originales (o incluso desee deshacerse de ellos). de ellos). En este caso, debe utilizar una solución basada en la clase PdfWriter .

Puede encontrar detalles en el capítulo 6 (especialmente la sección 6.4) de iText in Action - 2nd Edition . Se puede acceder al código de ejemplo de Java here y a las versiones de C # here .

Una muestra simple que usa PdfCopy es Concatenate.java / Concatenate.cs . La pieza central del código es:

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

Aquí, el pdf se puede definir como una List<byte[]> contiene los documentos de origen (apropiado para su caso de uso de la combinación de documentos intermedios en memoria) o como una List<String> contiene los nombres de los archivos de documentos de origen (apropiado si fusionas documentos desde el disco).

Una descripción general al final del capítulo al que se hace referencia resume el uso de las clases mencionadas:

  • Copia en PdfCopy : copia páginas de uno o más documentos PDF existentes. Principales desventajas: PdfCopy no detecta contenido redundante y falla al concatenar formularios.

  • PdfCopyFields : PdfCopyFields los campos de las diferentes formas en una sola forma. Se puede usar para evitar los problemas encontrados con los campos de formulario al concatenar formularios utilizando PdfCopy . El uso de la memoria puede ser un problema.

  • PdfSmartCopy : copia páginas de uno o más documentos PDF existentes. PdfSmartCopy puede detectar contenido redundante, pero necesita más memoria y CPU que PdfCopy .

  • PdfWriter : Genera documentos PDF desde cero. Puede importar páginas de otros documentos PDF. El principal inconveniente es que todas las funciones interactivas de la página importada (anotaciones, marcadores, campos, etc.) se pierden en el proceso.


Utilicé iTextsharp con c # para combinar archivos pdf. Este es el código que he usado.

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


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