In response to my post on Generating a PDF from Reporting Services, someone asked how I would join two PDFs. The problem is that I can't just take two PDF byte streams and run them together because there is PDF metadata that starts and ends each document. The way that I have gotten around this is use the ITextSharp library.
Our PDFs were stored in the database, so we grabbed each PDF and appended it to the first PDF (I didn't put the code in for the data reader--an astute reader of this entry should be able to figure that out). Here is the code similar to what we used, but we put it in several different methods to make the code more readable (your mileage may vary)--don't forget to add a reference to the ITextSharp library and include the imports statements (iTextSharp.text, iTextSharp.text.pdf) as part of your class:
' First set up the response and let the browser know a PDF is coming Response.Buffer = True Response.ContentType = "application/pdf" Response.AddHeader("Content-Disposition", "inline")
' Second, some setup stuff Dim MemStream As New System.IO.MemoryStream Dim doc As New iTextSharp.text.Document Dim reader As iTextSharp.text.pdf.PdfReader Dim numberOfPages As Integer Dim currentPageNumber As Integer Dim writer As iTextSharp.text.pdf.PdfWriter = iTextSharp.text.pdf.PdfWriter.GetInstance(doc, MemStream) doc.Open() Dim cb As iTextSharp.text.pdf.PdfContentByte = writer.DirectContent Dim page As iTextSharp.text.pdf.PdfImportedPage Dim rotation As Integer
' Third, append all the PDFs--THIS IS THE MAGIC PART Do While dr.Read If Not IsDBNull(dr("Report_pdf")) Then Dim sqlbytes() As Byte sqlbytes = dr("Report_pdf") reader = New iTextSharp.text.pdf.PdfReader(sqlbytes) numberOfPages = reader.NumberOfPages currentPageNumber = 0
Do While (currentPageNumber < numberOfPages) currentPageNumber += 1 doc.SetPageSize(PageSize.LETTER) doc.NewPage() page = writer.GetImportedPage(reader, currentPageNumber) rotation = reader.GetPageRotation(currentPageNumber) If (rotation = 90) Or (rotation = 270) Then cb.AddTemplate(page, 0, -1.0F, 1.0F, 0, 0, reader.GetPageSizeWithRotation(currentPageNumber).Height) Else cb.AddTemplate(page, 1.0F, 0, 0, 1.0F, 0, 0) End If Loop End IfLoop
' Finally Spit the stream out If MemStream Is Nothing Then Response.Write("No Data is available for output") Else Response.OutputStream.Write(MemStream.GetBuffer(), 0, MemStream.GetBuffer().Length) Response.OutputStream.Flush() Response.OutputStream.Close() MemStream.Close() End If
NOTE: One thing that I have not checked is whether the ITextSharp team has removed the dependency on the gziplib, but if you are already using the gziplib in your project, you are going to have to do a little work so that you don't have two referenced versions in your app.
