Geeks With Blogs

@bsherwin

Brian Sherwin's Blog Moving at the Speed of .Net

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 If
Loop

' 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.

Posted on Friday, June 29, 2007 9:31 AM | Back to top


Comments on this post: Merge PDFs using ITextSharp

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
I had some trouble getting this code to work. So I modified it closing the document and outputing the data using Response.BinaryWrite().

doc.Close();
Response.BinaryWrite(MemStream.GetBuffer());
Response.End();
MemStream.Close();

I'm sure there are other solutions but this one worked for me.
Left by Tom Harney on Oct 08, 2007 9:34 AM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
ting ting
Left by Sa on May 17, 2008 3:01 AM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
When I used this code I found that the first page was not sized correctly. I fixed the problem by calling doc.SetPageSize(PageSize.LETTER) before I called doc.Open().
Left by Matt Kannard on May 30, 2008 12:20 PM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
i'm a begginer... so, what's that:
Do While dr.Read? dr is not declared and got me kinda confused... sorry
Left by joaopsr on Jul 07, 2008 7:06 AM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
joaopsr:

Good question. After all this time, you are the first to ask that question. Basically, the dr was a SQLDataReader that was reading the PDFs from a SQL database as a BLOB. Maybe I ought to revisit this post and put up an example.
Left by Brian Sherwin on Jul 08, 2008 9:44 PM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
Thanks... i got there before the answer, but thanks anyway... i had to find another way because i'm building a web page (ASP.net) and no dataReaders... but i got it thanks to your guidelines
Left by joaopsr on Jul 09, 2008 4:19 AM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
This code works fine. I have used the code in a method namly GeneratePDF(). I have called the method from Button_Click(). The rest of the code in Button_Click is not executed after calling the GeneratePDF() method. Could you please let me know how to resovle the problem?
Left by Suba on Jul 18, 2008 6:04 AM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
Suba:

This is probably because the code in the example above is closing the Response.Outputstream because the assumption was that this was sending just the PDF to the users browser.
Left by Brian Sherwin on Jul 22, 2008 12:48 PM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
Thanks for the update. I have resolved the problem using HttpContext.
Left by Suba on Jul 23, 2008 1:01 AM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
I am trying to use this code. I am not pulling the PDF from the database rather I am using 2 physical files and trying to merge them into 1 and display on screen. The line reader = New iTextSharp.text.pdf.PdfReader("C:test.pdf") is creating issues when I watch the page.RootOutline property. I get this error: +RootOutline{"Value cannot be null. Parameter name: The writer in PdfContentByte is null."} iTextSharp.text.pdf.PdfOutline. Please advise.
Left by Anthony on Sep 15, 2008 9:39 AM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
Hi,

can u help me out? i have list of pdfs having writable fields in them. Now i have to write those fields in each pdfs and need to merge all the pdfs in to one as well let the final pdf to be writable.
i saw u've used writer instead of pdfstamper.
I can not use writer as i want final document as editable, so i tried using pdfstamper , but the contents are overlapping each one.

do u have any other idea?
Left by Tarang Pandya on Jan 12, 2009 1:31 PM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
I am trying to accomplish the same thing as Tarang. I am trying to merge multiple pdfs but then keep the final pdf editable. I have successfully used pdfstamper to do a single pdf file.

Also, how can Bookmarks be added to the pdf and then display or open the Bookmarks when the pdf file is loaded?
Left by James on Jan 25, 2009 1:54 AM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
Well you can use following code:
strSourceFiles is HashTable which contains the multiple editable files that needs to be merged.

Dim intFile As Integer = 0
If (strSourceFiles.Count >= 1) Then
Dim reader As New PdfReader(strSourceFiles(intFile).ToString())

Dim n As Integer = reader.NumberOfPages
Dim docDest As New Document(reader.GetPageSizeWithRotation(1))
Dim pdfcopy As New PdfCopyFields(New FileStream(strDestinationFile, FileMode.Create))

'pdfcopy.SetEncryption(Nothing, Nothing, PdfWriter.AllowCopy, False)
docDest.Open()
While (intFile < strSourceFiles.Count)
pdfcopy.AddDocument(reader)
intFile = intFile + 1
If (intFile < strSourceFiles.Count) Then
If Not reader Is Nothing Then
reader.Close()
reader = Nothing
End If
reader = New PdfReader(strSourceFiles(intFile).ToString())
n = reader.NumberOfPages
End If
End While
docDest.Close()
isDone = True
pdfcopy.Close()
End If


--- But the limitation with this is we can not save it locally once we fill the form. We must have to print the filled form and then we can save it for our purpose.
Left by Tarang Pandya on Feb 13, 2009 4:20 PM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
I want to input reader from reportdocument(crystal report), because I want to combine reportdocument.

reader = New iTextSharp.text.pdf.PdfReader(sqlbytes)

how can I do that?
Left by layyuddi on Jul 24, 2009 5:17 AM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
Brian,
Thanks for this wonderful article. It works great. But I have a question. After getting the binary data from db instead of directly displaying is there a way if I want to store the file in local machine how can I do that.

Thanks in advance
Left by srini on Oct 10, 2009 8:13 PM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
Hi
thanks for this samples.
I use the pdfStamper to fill out fields and want to merge the pdfs and put the output-stream to the asp.net Response.OutputStream. Has sombedody done this yet?
thanks for help
Left by Hajo on Nov 12, 2009 4:41 AM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
when i call new pdfreader(sqlbytes) it throw exception pdf header signature is not found
can u help me please?
Left by Eman on Nov 30, 2009 7:32 AM

# re: Merge PDFs using ITextSharp
Requesting Gravatar...
how do you set the default zoom/magnify of the pdf? Currently it is 125%, but I would like it to be 68%.
Left by Allen on Jan 20, 2010 5:17 PM

Your comment:
 (will show your gravatar)
 


Copyright © Brian Sherwin | Powered by: GeeksWithBlogs.net | Join free