Reputation: 512
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
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
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