I wanted to add a way to optionally render the PDF in landscape mode, so this was what I ultimately came up with.
public static ReturnValue ConvertHtmlToPdfAsBytes(string HtmlData, bool Landscape = false)
{
// variables
ReturnValue Result = new ReturnValue();
// do some additional cleansing to handle some scenarios that are out of control with the html data
HtmlData = HtmlData.ReplaceValue("<br>", "<br />");
// convert html to pdf
try
{
// create a stream that we can write to, in this case a MemoryStream
using (var stream = new MemoryStream())
{
// create an iTextSharp Document which is an abstraction of a PDF but **NOT** a PDF
using (var document = new Document())
{
// portrait vs landscape
if (Landscape)
{
document.SetPageSize(PageSize.A4.Rotate());
}
// create a writer that's bound to our PDF abstraction and our stream
using (var writer = PdfWriter.GetInstance(document, stream))
{
// open the document for writing
document.Open();
// read html data to StringReader
using (var html = new StringReader(HtmlData))
{
XMLWorkerHelper.GetInstance().ParseXHtml(writer, document, html);
}
// close document
document.Close();
}
}
// get bytes from stream
Result.Data = stream.ToArray();
// success
Result.Success = true;
}
}
catch (Exception ex)
{
Result.Success = false;
Result.Message = ex.Message;
}
// return
return Result;
}
The ReturnValue class was simply a helper class that looks like this: // return value class
public class ReturnValue
{
// constructor
public ReturnValue()
{
this.Success = false;
this.Message = string.Empty;
}
// properties
public bool Success = false;
public string Message = string.Empty;
public Byte[] Data = null;
}
We also had another method to physically create the PDF file in case you didn't want just the bytes array directly, for example: public static ReturnValue ConvertHtmlToPdfAsFile(string FilePath, string HtmlData)
{
// variables
ReturnValue Result = new ReturnValue();
try
{
// convert html to pdf and get bytes array
Result = ConvertHtmlToPdfAsBytes(HtmlData: HtmlData);
// check for errors
if (!Result.Success)
{
return Result;
}
// create file
File.WriteAllBytes(path: FilePath, bytes: Result.Data);
// result
Result.Success = true;
}
catch(Exception ex)
{
Result.Success = false;
Result.Message = ex.Message;
}
// return
return Result;
}
It's important to remember that in order for this to work, you must have valid well-formed HTML; otherwise you can certainly expect for iTextSharp to throw an error. But if you have control over the HTML that you need to convert, this solution is great, and produces very nice PDF files.It's worth noting that in our case we didn't need to pass the CSS in separately using the overloaded ParseXHtml constructor, ParseXHtml(PdfWriter writer, Document doc, Stream inp, Stream inCssFile), because we were including our CSS styles in our HTML data string instead, which for our solution was a bit cleaner.
Matt Pavey is a Microsoft Certified software developer who specializes in ASP.Net, VB.Net, C#, AJAX, LINQ, XML, XSL, Web Services, SQL, jQuery, and more. Follow on Twitter @matthewpavey

0 comments: