creating an XPS Document from a FlowDocument and attach it on the fly
Asked Answered
M

1

8

I have a FlowDocument that I want to convert to an XPS Document and attach it to an e-mail and send it all together. I'm using this code

public static Stream FlowDocumentToXPS(FlowDocument flowDocument, int width, int height)
{
    MemoryStream stream = new MemoryStream();
    using (Package package = Package.Open(stream, FileMode.Create,FileAccess.ReadWrite))
    {         
        using (XpsDocument xpsDoc = new XpsDocument(package, CompressionOption.Maximum))
        {
            xpsDoc.AddFixedDocumentSequence();
            XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(xpsDoc), false);
         
            DocumentPaginator paginator = ((IDocumentPaginatorSource)flowDocument).DocumentPaginator;
            paginator.PageSize = new System.Windows.Size(width, height);              
            rsm.SaveAsXaml(paginator);                  
            rsm.Commit();
        }

        return stream;
    }
}

Then I attach it using this code:

Attachment xps = new Attachment(FlowDocumentToXPS(FD, 768, 676), "FileName.xps", "application/vnd.ms-xpsdocument");

where FD is the FlowDocument I want to convert , I'm receiving 0.0KB size XPS file attached and it can't be open with the XPS Viewer , what I'm missing here ?

Mercymerdith answered 23/7, 2011 at 8:54 Comment(13)
Are you sure you're not swallowing an exception somewhere? I don't think you have to add the FixedSequence.Salesman
perhaps the stream is closed on leaving the using blockPoi
@Henk Holterman, I checked the ouput no exception occured , and you are right , I was trying different things that brought this FixedSequence , I removed but the problem still thereMercymerdith
@Poi I tried to return the stream inside the using block, same result.Mercymerdith
@Musaab, even though you moved it, the using may still be releasing it. Try removing the using block and if that works, you may need to free up the 'using' resources outside the method.Poi
I'd answer but Kenny should... 1) do NOT dispose of the stream. It seems odd, yes, but if you close the stream that backs the XPS package, you will get bupkis. Remove it from any and all using blocks. 2) once you create the XPS document, you need to back that stream up to 0 before you do anything with it.Aloisius
@Will thanks alot , from my searches on this specific topic , I found your name everywhere I was going to ask you directly, I partially solved it by just saving to disk and then uplaoding as an attachment, I prefere some modification to this code though, if Kenny didn't , I'm waiting for yours.Mercymerdith
I forget to mention that I don't really understand what are you trying to explain , i.e. how to back up the stream to 0 ?Mercymerdith
@Musaab: A stream, at its simplest, is a sequential list of bytes and a pointer to the last byte. When you write to a stream backing an XPS document, additional bytes are added, and the pointer moves again to the last byte. If you then hand the stream to someone else that writes that stream somewhere (file, http client) if you don't set that pointer to the beginning of the stream, you will get nothing as the pointer is at the end of the stream. Usually you accomplish this by stream.Position = 0Aloisius
@Will, I understood , however I couldn't apply it there on my code , I tried several times but it keeps sending a 0 KB document, would you please just write an answer, it will be much appreciatedMercymerdith
@Musaab: can't answer without seeing where in your code you call FlowDocumentToXPS and then attach it to an email. Might have to do with a lot of things, including the email being processed after the backing stream has been collected... Have you ensured that 1) the stream has >0 bytes and that 2) Position is 0 before attaching?Aloisius
finally , it did worked , thanks alot , now what should I do to close the topic, I guess you may write your last comment as an answer so that I accept it as the final answer.Mercymerdith
About 11 years late to the conversation. I tried using this code but my page size gets all screwed up after converting. The flow document was defined with a Width and Height of 21cm and 29.7 respectively but the output document has 2 columns of text per page for some reason.Cimabue
M
2

Solved , this is the final code which worked:

    public static MemoryStream FlowDocumentToXPS(FlowDocument flowDocument, int width, int height)
    {
        MemoryStream stream = new MemoryStream();
        using (Package package = Package.Open(stream, FileMode.Create, FileAccess.ReadWrite))
        {
            using (XpsDocument xpsDoc = new XpsDocument(package, CompressionOption.Maximum))
            {                  
                XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(xpsDoc), false);
                DocumentPaginator paginator = ((IDocumentPaginatorSource)flowDocument).DocumentPaginator;
                paginator.PageSize = new System.Windows.Size(width, height);
                rsm.SaveAsXaml(paginator);
                rsm.Commit();                
            }
        }
        stream.Position = 0;
        Console.WriteLine(stream.Length);
        Console.WriteLine(stream.Position);
        return stream;   
    }

Then I attach it using this code:

Attachment xps = new Attachment(FlowDocumentToXPS(FD, 768, 676), "FileName.xps", "application/vnd.ms-xpsdocument");

where FD is the FlowDocument I want to convert.

Mercymerdith answered 28/7, 2011 at 13:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.