Question

I have a static method like this and I am using ITextSharp to generate PDF..

public static byte[] createPDF(string htmlstr) {
            var  html = @"<?xml version=""1.0"" encoding=""UTF-8""?>
             <!DOCTYPE html 
                 PUBLIC ""-//W3C//DTD XHTML 1.0 Strict//EN""
                ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"">
             <html xmlns=""http://www.w3.org/1999/xhtml"" xml:lang=""en"" lang=""en"">
                <head>
                    <title>Minimal XHTML 1.0 Document with W3C DTD</title>
                </head>
              <body>
                " + htmlstr + "</body></html>";

            // step 1: creation of a document-object
            Document document = new Document(PageSize.A4, 30, 30, 30, 30);

            MemoryStream msOutput = new MemoryStream();

            // step 2:
            // we create a writer that listens to the document
            // and directs a XML-stream to a file
            PdfWriter.GetInstance(document, msOutput);

            // step 3: we create a worker parse the document
            HTMLWorker worker = new HTMLWorker(document);

            // step 4: we open document and start the worker on the document
            document.Open();
            worker.StartDocument();

            // step 5: parse the html into the document
            worker.Parse(new StringReader(html));

            // step 6: close the document and the worker
            worker.EndDocument();
            worker.Close();
            document.Close();

            byte[] buffer = new byte[msOutput.Length];

            using (MemoryStream ms = new MemoryStream())
            {
                int read;
                while ((read = msOutput.Read(buffer, 0, buffer.Length)) > 0)
                {
                    ms.Write(buffer, 0, read);
                }

                msOutput.Close();

                return ms.ToArray();
            }
    }

When I was debugging, after I pass worker.Parse(new StringReader(html)), the MemoryStream.Length does not work.

I have seen some examples out there using FileStream but I do not want to create a new file. Why is the code erroring?

Was it helpful?

Solution

The basic problem that you are running into is that by default the PdfWriter object will close the stream that you are writing to. PdfWriter.GetInstance() actually returns an object that you can set additional properties and you specifically want to call:

writer.CloseStream = false;

Your MemoryStream to byte[] to MemoryStream to byte[] confuses me, was that just a way to try to work around the above problem?

Beginning with iTextSharp 5.0.6 most of the primary classes such as Document and PdfWriter all implement IDisposable which, at least for me, along with the using pattern makes code much easier to read and debug. You also don't have to think about closing things as much. Give this a shot:

public static byte[] createPDF(string htmlstr) {
    var html = @"<?xml version=""1.0"" encoding=""UTF-8""?>
     <!DOCTYPE html 
         PUBLIC ""-//W3C//DTD XHTML 1.0 Strict//EN""
        ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"">
     <html xmlns=""http://www.w3.org/1999/xhtml"" xml:lang=""en"" lang=""en"">
        <head>
            <title>Minimal XHTML 1.0 Document with W3C DTD</title>
        </head>
      <body>
        " + htmlstr + "</body></html>";


    // step 1: creation of a document-object
    using (Document document = new Document(PageSize.A4, 30, 30, 30, 30)) {
        using (MemoryStream msOutput = new MemoryStream()) {

            // step 2:
            // we create a writer that listens to the document
            // and directs a XML-stream to a file
            using (PdfWriter writer = PdfWriter.GetInstance(document, msOutput)) {

                // step 3: we create a worker parse the document
                HTMLWorker worker = new HTMLWorker(document);

                // step 4: we open document and start the worker on the document
                document.Open();
                worker.StartDocument();


                // step 5: parse the html into the document
                worker.Parse(new StringReader(html));

                // step 6: close the document and the worker
                worker.EndDocument();
                worker.Close();
                document.Close();
            }

            // Return the bytes
            return msOutput.ToArray();
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top