Merging Memory Streams to create a http PDF response in c#

12,715

Here's a simple merge method that copies PDF files into one PDF. I use this method quite often when merging pdfs. Hope it helps.

    public MemoryStream MergePdfForms(List<byte[]> files)
    {
        if (files.Count > 1)
        {
            PdfReader pdfFile;
            Document doc;
            PdfWriter pCopy;
            MemoryStream msOutput = new MemoryStream();

            pdfFile = new PdfReader(files[0]);

            doc = new Document();
            pCopy = new PdfSmartCopy(doc, msOutput);

            doc.Open();

            for (int k = 0; k < files.Count; k++)
            {
                pdfFile = new PdfReader(files[k]);
                for (int i = 1; i < pdfFile.NumberOfPages + 1; i++)
                {
                    ((PdfSmartCopy)pCopy).AddPage(pCopy.GetImportedPage(pdfFile, i));
                }
                pCopy.FreeReader(pdfFile);
            }

            pdfFile.Close();
            pCopy.Close();
            doc.Close();

            return msOutput;
        }
        else if (files.Count == 1)
        {
            return new MemoryStream(files[0]);
        }

        return null;
    }

Step 4 try:

        rptCS.Close();
        rptCS.Dispose();
        rptAd.Close();
        rptAd.Dispose();

        Response.Clear();
        Response.ContentType = "application/pdf";
        Response.AddHeader("Content-Disposition", 
    "attachment; filename=" + 
    "Application of " + FullName.Trim() + ".pdf");
        Response.BinaryWrite(ms.ToArray());
        ApplicationInstance.CompleteRequest();
Share:
12,715

Related videos on Youtube

Chandanan
Author by

Chandanan

Updated on June 04, 2022

Comments

  • Chandanan
    Chandanan almost 2 years

    I am trying to merge 2 crystal reports into single pdf file and I'm using Itextsharp v5.1.1. But it says the document cannot be opened. It might be corrupted. There are no build errors. but the pdf is malformed and cant be opened. Here is the order I chose to accomplish this.

    1. Export the Crystal report to MemoryStream1 in pdf format
    2. Export the second report into MemoryStream2.
    3. Merge the Memory Streams
    4. Send the Streams to Http Output Response as PDF.

    Here is the Code for each step in the order.

       /// Get the Dataset from Stored Procedure for the CSSource Report
       dsCS = CSData.GetUSSourceXML(ds_input);
       /// Create the Report of type CSsource
       rptCS = ReportFactory.GetReport(typeof(CSsource));
       rptCS .SetDataSource(dsCS);
       /// Set the Parameters to the CS report
       rptCS .ParameterFields["Parameterid"].CurrentValues.Clear();
       rptCS .SetParameterValue("Parameterid", PID);
       //// Serialize the Object as PDF                    
       msCS=(MemoryStream)rptCS .ExportToStream(ExportFormatType.PortableDocFormat);
    

    For Step 2

       /// Get the Dataset from Stored Procedure for the Aden Report
       dsAd = CSData.GetAdden(ds_input);
       /// Create the Report of type Aden
       rptAd = ReportFactory.GetReport(typeof(Aden));
       rptAd.SetDataSource(dsAd );
       /// Set the Parameters to the Aden report
       rptAd.ParameterFields["Parameterid"].CurrentValues.Clear();
       rptAd.SetParameterValue("Parameterid", PID);
       //// Serialize the Object as PDF                    
       msAD = (MemoryStream)rptAd.ExportToStream(ExportFormatType.PortableDocFormat);
    

    For Step 3

      System.Collections.Generic.List<byte[]> sourceFiles = new List<byte[]>();
      sourceFiles.Add(msCS.ToArray());
      sourceFiles.Add(msAD.ToArray());
      PdfMerger mpdfs = new PdfMerger();
      /// ms is the Memory stream to which both the streams are added
      ms=mpdfs.MergeFiles(sourceFiles);
    

    MergeFiles method is as follows

     public MemoryStream MergeFiles(Generic.List<byte[]> 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;
        }
    

    Step 4 to Serialize the Memory stream as PDF

      // ms is the memory stream which is to be converted to PDF
      Response.Clear();
            Response.ClearContent();
            Response.ClearHeaders();
            Response.ContentType = "application/pdf";
            Response.Charset = string.Empty;
            Response.AddHeader("Content-Disposition", 
            "attachment; filename=" + 
            "Application of " + FullName.Trim() + ".pdf");
            //Write the file directly to the HTTP content output stream.
            Response.OutputStream.Write(ms.ToArray(), 0, 
                   Convert.ToInt32(ms.Length));
            Response.OutputStream.Flush();
            Response.OutputStream.Close();
            rptCS.Close();
            rptCS.Dispose();
            rptAd.Close();
            rptAd.Dispose();
    

    Thanks for all those Developers helping me with this. This is Urgent because it has to go production in a day or 2. Please respond.

    Chandanan.

  • Chandanan
    Chandanan almost 13 years
    Jonathan, thanks for the reply. I used the above code but I still dont think this helped. The error that I came accross is 'Cannot open a closed stream'. Then I commented 3 lines of code in the above function as follows. //pdfFile.Close();//pCopy.Close();//doc.Close(); Then there is no runtime error and then I could save a file. but when I opened it, it is blank as usual and corrupted. What version of Itextsharp are you using? I am using the latest 5.1.1 version. I can try using your version with your code. Thanks so much.
  • Jonathan
    Jonathan almost 13 years
    @Chandanan I use itextsharp 5.1.0 and that shoudn't be the issue with your code. I'm thinking you may have an issue with step 4. see my edit.
  • Chandanan
    Chandanan almost 13 years
    Jonathan, I could get this work!!! Thanks man, Just a little change in the sequence that I did. Just reordered the 4th step and put these 4 lines in the bottom and it worked. rptCS.Close(); rptCS.Dispose(); rptAd.Close(); rptAd.Dispose(); Thanks a ton man. :)
  • LacOniC
    LacOniC about 8 years
    This is life saver. Thank you.