capn
capn

Reputation: 512

"The document is not open" error only in production with iTextSharp

I am getting a "The document is not open" error in iTextSharp, but only in production. The code runs fine on my dev machine and in staging. I have the same permissions set in the Temp folder on the stage server.

public static byte[] ConvertHtmlToPdf(string html)
    {
        html = HtmlPostProcessor.Process(html);
        byte[] fileData = null;
        string tempPath = ConfigurationManager.AppSettings["TempDirectory"];
        string tempPDFFile = Path.Combine(tempPath, Guid.NewGuid() + ".pdf");
        int num = FontFactory.RegisterDirectory(@"C:\Windows\Fonts");

        using (FileStream fs = new FileStream(tempPDFFile, FileMode.Create))
        {
            using (Document document = new Document(PageSize.LETTER, 50, 50, 50, 50))
            {
                document.Open();
                PdfWriter.GetInstance(document, fs);
                using (StringReader stringReader = new StringReader(html))
                {

                    List<IElement> parsedList = HTMLWorker.ParseToList(stringReader, null);
                    foreach (IElement item in parsedList)
                    {
                        document.Add(item);
                    }
                }
            }
        }

        FileStream generatedPDF = File.Open(tempPDFFile, FileMode.Open);
        fileData = new byte[(int)generatedPDF.Length]; 
        int result = generatedPDF.Read(fileData, 0, (int)generatedPDF.Length);

        generatedPDF.Close();

        File.Delete(tempPDFFile);

        return fileData;
    }

A pdf file does get created, so I know it runs past

using (FileStream fs = new FileStream(tempPDFFile, FileMode.Create))

at the very least.

This code runs just fine in dev and staging, but it throws an error in production. Any thoughts as to why that could be?

Upvotes: 4

Views: 9666

Answers (2)

capn
capn

Reputation: 512

Using kuujinbo's suggestions about improving the code, it now looks like this:

    public static byte[] ConvertHtmlToPdf(string html)
    {
        html = HtmlPostProcessor.Process(html);
        byte[] fileData = null;
        int num = FontFactory.RegisterDirectory(@"C:\Windows\Fonts");

        using (MemoryStream ms = new MemoryStream(html.Length))
        {
            using (Document document = new Document(PageSize.LETTER, 50, 50, 50, 50))
            {
                PdfWriter.GetInstance(document, ms);
                using (StringReader stringReader = new StringReader(html))
                {

                    List<IElement> parsedList = HTMLWorker.ParseToList(stringReader, null);
                    document.Open();
                    foreach (IElement item in parsedList)
                    {
                        document.Add(item);
                    }
                }
            }

            fileData = ms.ToArray();
        }
        return fileData;
    }

The problem was that inside the:

using (Document document = new Document(PageSize.LETTER, 50, 50, 50, 50))

statement, another exception was being thrown, in my case it was:

WebException: Unable to connect to the remote server

which happened because an image I was using that was linked inside the HTML document, that was being converted to a PDF, was pointing to another website hosted on the same server. The server had internal and external IP addresses, but I forgot to edit the hosts file on the server so that redirects to itself using those DNS names would use internal addresses instead of the external ones.

The reason the Exception message was "The document is not open", is because (FYI: I'm assuming here) since I was in a using block that basically acts as a "finally" statement, anytime there is an exception in the iText library the Document closes, and when the using tries to call Dispose (which is what showed up in the stack trace) iText errors out because the Document object must already be closed.

Upvotes: 3

goTo-devNull
goTo-devNull

Reputation: 9372

Didn't notice it at first glance, but from your code above:

document.Open();
PdfWriter.GetInstance(document, fs);

The order needs to be reversed:

PdfWriter.GetInstance(document, fs);
document.Open();

In other words, you need the PdfWriter before you try and open the Document

Upvotes: 16

Related Questions