Forum How do I...?

.NET Streams

Anonymous
Prince XML seems like a great product! But I am having difficulty getting one important feature to work. I would like to take a string of XHTML with an embedded stylesheet, convert it to a stream, pass the stream to Prince, and retrieve a stream for the PDF content.

The overloaded version of the Convert method that accepts a System.IO.Stream as input and returns a System.IO.Stream as output seems like it will do exactly what I need. However, when trying to call this method the log file lists the following error:

Wed Aug 29 20:24:54 2007: ---- begin
Wed Aug 29 20:24:54 2007: -: error: could not load input file
Wed Aug 29 20:24:54 2007: error: no input documents to process
Wed Aug 29 20:24:54 2007: finished: failure
Wed Aug 29 20:24:54 2007: ---- end

Maybe I am setting up the code incorrectly? Any guidance would be appreciated. I am using the following VB.NET code:

Dim oPrince As New Prince("C:\Program Files\Prince\Engine\bin\prince.exe")
Using oInStream As System.IO.Stream = New System.IO.MemoryStream
    ' Create a byte array from the XHTML string 
    '   and write it to the input memory stream.
    Dim enc As New UTF8Encoding
    Dim arrBytData() As Byte = enc.GetBytes(sXHTML)
    oInStream.Write(arrBytData, 0, arrBytData.Length)

    ' Create an output memory stream for the PDF output.
    Using oOutStream As System.IO.Stream = New System.IO.MemoryStream
        oPrince.SetHTML(True)
        oPrince.SetLog("c:\inetpub\http\pdf\" & PDFName & ".log")
        If Not oPrince.Convert(oInStream, oOutStream) Then
            Throw New Exception("There was an error creating the PDF.")
        End If
        
        oOutStream.Close()
    End Using

    oInStream.Close()
End Using
mikeday
I think the problem is that after writing to the MemoryStream the position will be at the end, and then Prince will try to read from it and not get anything. If you want to do it this way you'll need to seek back to the beginning of the stream before passing it to Prince, like this:
oInStream.Seek(0, SeekOrigin.Begin)

Then Prince can read everything that you've written to it.
mikeday
It might be a good idea to add a ConvertString() method to the .NET interface, as this is a common usage pattern and it should be easier to do. I've added this issue to the roadmap.
Anonymous
That solved the problem. Thanks for your help! I agree that having a ConvertString() method might make this common scenario easier to implement.
fuhaili
I am doing the same thing as here, but the pdf is always not showing up, it got error message, my code is here, can anybody to help me to fix it:
in the page_load method of the default page:

Dim constr As String = ConfigurationManager.AppSettings("DSN")
        Dim pdf_byte() As Byte
        Dim oPrince As New Prince("C:\Program Files\Prince\Engine\bin\prince.exe")

        Using oInStream As System.IO.Stream = New System.IO.MemoryStream
            ' Create a byte array from the XHTML string 
            '   and write it to the input memory stream. 
            Dim sXHTML As String = "<html>" _
                & "<head><title>Untitled Page</title></head><body> <form><div>" _
                & "<b>hello</b></div></form></body></html>"
            Dim PDFName As String = "hello"
            Dim enc As New UTF8Encoding
            Dim arrBytData() As Byte = enc.GetBytes(sXHTML)
            oInStream.Write(arrBytData, 0, arrBytData.Length)
            oInStream.Seek(0, IO.SeekOrigin.Begin)

            ' Create an output memory stream for the PDF output. 
            Using oOutStream As System.IO.Stream = New System.IO.MemoryStream
                oPrince.SetHTML(True)
                oPrince.SetLog("~\pdf\" & PDFName & ".log")
                If Not oPrince.Convert(oInStream, oOutStream) Then
                    Throw New Exception("There was an error creating the PDF.")
                End If
                pdf_byte = New Byte(CType(oOutStream.Length, Integer)) {}
                oOutStream.Read(pdf_byte, 0, oOutStream.Length)
                oOutStream.Close()
            End Using
            oInStream.Close()
        End Using

        Response.Clear()
        Response.AddHeader("Content-Type", "binary/octet-stream")
        Response.AddHeader("Content-Disposition", "attachment; filename=" & "Rendered.pdf" & "; size=" _
                & pdf_byte.Length.ToString())
        Response.Flush()
        Response.BinaryWrite(pdf_byte)
        Response.Flush()
        Response.End()

Thanks in advance!
mikeday
The content type should be "application/pdf" (or perhaps you mean "application/octet-stream", there is no "binary/octet-stream" type).

Are you getting error messages from Prince, or error messages from ASP, or error messages from the browser?
mikeday
Another thing, if you're reading from the output memory stream, then you'll probably need to seek back to the beginning of that as well, as after Prince has written the PDF file to it the offset will be at the end, not the beginning.
mikeday
Today we have released a new version of the .NET interface that includes a ConvertString() method.