This is a migrated thread and some comments may be shown as answers.

PdfStreamWriter.WritePage to a MemoryStream/Byte() not working

2 Answers 145 Views
PdfProcessing
This is a migrated thread and some comments may be shown as answers.
Shawn Krivjansky
Top achievements
Rank 1
Shawn Krivjansky asked on 15 Aug 2019, 12:20 AM

When writing to a FileStream with PdfStreamWriter.WritePage, either implicitly or after the PdfStreamWriter loses scope...  A PDF document gets created correctly specifically with the ending portion of the PDF document that handles the %EOF and the portions just prior to that.

When this same process is done with a MemoryStream (not a file) for the purposes of taking that "PDF DOCUMENT" and saving the byte() to a database, that ending part of the PDF document doesn't get created... and thus it becomes a corrupt (unreadable) PDF file.  This ending portion of the PDF document that I'm referring to looks like this: (example):

xref
0 26
0000000000 65535 f
0000350400 00000 n
0000350089 00000 n
0000000017 00000 n
0000000204 00000 n
0000000440 00000 n
0000000699 00000 n
0000150134 00000 n
0000150319 00000 n
0000150473 00000 n
0000150732 00000 n
0000232360 00000 n
0000232502 00000 n
0000232814 00000 n
0000232842 00000 n
0000233014 00000 n
0000233544 00000 n
0000233799 00000 n
0000346061 00000 n
0000346138 00000 n
0000346322 00000 n
0000346637 00000 n
0000346892 00000 n
0000350305 00000 n
0000350459 00000 n
0000350528 00000 n
trailer
<</Size 26 /Root 24 0 R /ID [<b3a969414ce82cc43f271ef24e965a21> <b3a969414ce82cc43f271ef24e965a21>] >>
startxref
350975
%%EOF

 

What do I have to do after .WritePage with a backing MemoryStream... to eventually grab that byte() with a complete PDF document that includes the %%EOF piece... like for example:

Dim contentLength As Int64 = msOutputStream.Length
 Dim aryBuffer(contentLength - 1) As Byte
 aryBuffer = msOutputStream.ToArray

After the WritePage, the above will NOT include that ending segment of the PDF document/file.

I can't really .Close the MemoryStream, because then it isn't accessible at all... Does it need to be a part of a USING statement in some way?  I have the PdfStreamWriter in a USING... and I do NOT need to have the FileStream as part of a USING and it works correctly.

 

Some full sample code:

Dim documentsToMerge As String() = {"d:\SignaturePageToAppend.pdf"}
Dim msOutputStream As MemoryStream = New MemoryStream()
 
Using memoryWriter As Pdf.Streaming.PdfStreamWriter = New Pdf.Streaming.PdfStreamWriter(msOutputStream)
    Dim pdfOutputProv As Pdf.PdfFormatProvider = New Pdf.PdfFormatProvider(msOutputStream)
 
    For Each documentName As String In documentsToMerge
 
        'This is initializing the MemoryStream with a good Byte() PDF from a DB
        Dim msAddedPagePDF As MemoryStream = New MemoryStream(docAddedPage.FSDocument)
 
        Using fileToMerge As Pdf.Streaming.PdfFileSource = New Pdf.Streaming.PdfFileSource(msAddedPagePDF)
 
            Dim pdfAddedPage1 As Pdf.Streaming.PdfPageSource = fileToMerge.Pages.FirstOrDefault
            memoryWriter.WritePage(pdfAddedPage1)
 
        End Using
 
 
        'TBD
        Dim contentLength As Int64 = msOutputStream.Length
        Dim aryBuffer(contentLength - 1) As Byte
        aryBuffer = msOutputStream.ToArray
 
        'aryBuffer will NOT include the ending PDF segment to complete the PDF document
         
        'Saving Byte() to DB
        'docSource.FSDocument = aryBuffer
        'trDocumentRepository.Update(docSource)
        'trDocumentRepository.FlushAndSaveChanges()
 
    Next
End Using

 

 

 

2 Answers, 1 is accepted

Sort by
0
Shawn Krivjansky
Top achievements
Rank 1
answered on 15 Aug 2019, 08:52 PM

Just FYI...

I figured it out.

The key is adding the boolean option on the PdfStreamWriter creation to LEAVE THE STREAM OPEN (after the writer falls out of scope)... and then moving any/all stream data gathering/saving until AFTER the PdfStreamWriter falls out of scope... Once it falls out of scope, it will add the ending segment that I was missing.

Using memoryWriter As Pdf.Streaming.PdfStreamWriter = New Pdf.Streaming.PdfStreamWriter(msOutputStream, True)

 

0
Tanya
Telerik team
answered on 19 Aug 2019, 08:50 AM
Hello Shawn,

I am happy to hear that you managed to find the solution.

Indeed, the PDF file is being completed when the writer disposes. That is why, getting the file data before disposing the object will lead to invalid document. You can find more information in the PdfStreamWriter topic in our documentation.

Regards,
Tanya
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Sean
Top achievements
Rank 1
commented on 26 Aug 2021, 01:13 PM | edited

 

There is indeed scant documentation that uses a FileStream and not a MemoryStream that does not cover this issue. I have just run into it too - was about to raise a ticket when I came across this thread. Thanks to Shawn for following up with a solution.

 

It might be worth adding to the documentation... or at least a sample with a MemoryStream as not everyone wants to create a physical file in this online world...

Tanya
Telerik team
commented on 30 Aug 2021, 02:51 PM

Hi Sean,

Thank you for sharing your feedback. I completely agree with you and we will update the documentation to describe that scenario in one of the next uploads of the website.

Tags
PdfProcessing
Asked by
Shawn Krivjansky
Top achievements
Rank 1
Answers by
Shawn Krivjansky
Top achievements
Rank 1
Tanya
Telerik team
Share this question
or