.Net, ASP.NET, C#, iTextSharp, Programming, Software

C# iTextSharp Stream or Save Content using XMLWorkerHelper

iTextSharp to PDF
iTextSharp to PDF

When working with the iTextSharp PDF generation libraries for C#, you can use the XMLWorkerHelper object to export a Web page to PDF format. However while doing so you will run into the question of how best to serve the PDF up to your users.

Bottom line here is that you have two ways of doing so:

  1. You can stream the PDF document directly to the client browser
  2. You can create the PDF on the Web Server’s hard-drive and then redirect the client browser to the file

Each method has its pros and cons which you will have to weigh when deciding which technique to use.

At the end of this article I will give the example code in C# of how to generate a PDF using each of these two techniques.

Feel free to read some other articles I have written about using the iTextSharp PDF generation libraries with your .NET code.

Advantages of Saving the PDF to the Server’s Hard Drive

  1. You will have a permanent copy of the report that the user generated. You can keep this for reference purposes and direct the user to it in future.
  2. You have control over the output window if you embed the PDF in a JavaScript window.open browser window.
  3. The user does not see a prompt to download the PDF or a security warning prompt when you embed the PDF in JavaScript window.open browser window.

Advantages of Directly Streaming the File to the Client Browser

  1. You do not have to grant write permissions to the .NET worker process to a folder on the Web Server. Doing do in some environments can be a tough sell, so the ability to stream the file without needing any server permission modifications is a great feature.

Disadvantages of Saving the PDF to the Server’s Hard Drive

  1. Saving the file to the Server’s drive requires that you set the .NET service account on the server with enough permission to write to a folder on the drive. These permissions may be difficult to get depending on your level of access to the Web server.

Disadvantages of Directly Streaming the File to the Client Browser

  1. When streaming out the PDF file you cannot control the window size or any user-specific setting such as the PDF zoom level. This is entirely dependent on the user’s settings.
  2. Another possible annoyance for users is that the user is prompted to confirm if they want to open or save the file, rather than having the file directly streamed.
  3. The streamed file is not permanent and is gone as soon as it is generated. A file saved to the server can always be referenced.

These reasons alone may be enough to make you prefer to save the generated file to the Web Server’s hard-drive.

—- THE EXAMPLE CODE —-

CSharpTestReport.aspx

This is the main report page that both other pages will use to turn into a PDF report. It’s a simple example consisting of a hard-coded GridView control.

<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 Hashtable m_testData = new Hashtable();
 protected void Page_Load(object sender, System.EventArgs e)
 {
 m_testData.Add("test_1_id", "test_1_value");
 m_testData.Add("test_2_id", "test_2_value");
 m_testData.Add("test_3_id", "test_3_value");
 m_testData.Add("test_4_id", "test_4_value");
 GridView1.DataSource = m_testData;
 GridView1.DataBind();
 }
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <title></title>
</head>
<body>
 <form id="form1" runat="server">
 <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
 <Columns>
 <asp:TemplateField HeaderText="key">
 <EditItemTemplate>
 <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("key") %>'></asp:TextBox>
 </EditItemTemplate>
 <ItemTemplate>
 <asp:Label ID="Label1" runat="server" Text='<%# Bind("key") %>'></asp:Label>
 </ItemTemplate>
 </asp:TemplateField>
 <asp:TemplateField HeaderText="value">
 <EditItemTemplate>
 <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("value") %>'></asp:TextBox>
 </EditItemTemplate>
 <ItemTemplate>
 <asp:Label ID="Label2" runat="server" Text='<%# Bind("value") %>'></asp:Label>
 </ItemTemplate>
 </asp:TemplateField>
 </Columns>
</asp:GridView>
 </form>
</body>
</html>

CSharpTestStream.aspx

This page shows you how to read the report generated in the CSharpTestReport.aspx page, and then how to stream the report as a PDF file directly to the client browser.

<%@ Page Language="C#" %>
<%@ Import Namespace="iTextSharp.tool.xml" %>
<%@ Import Namespace="iTextSharp.text.pdf" %>
<%@ Import Namespace="System.IO" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 protected void Button1_Click(object sender, System.EventArgs e)
 {
 string strFileShortName = "test" + DateTime.Now.Ticks + ".pdf";
 var memStrOutput = new MemoryStream();
 StringWriter strWriter = new StringWriter();
 Server.Execute("CSharpTestReport.aspx", strWriter);
 string strHtml = strWriter.ToString();
 using (iTextSharp.text.Document docWorkingDocument = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4, 1, 1, 0, 0)){
 PdfWriter pdfWrite = PdfWriter.GetInstance(docWorkingDocument, memStrOutput);
 docWorkingDocument.Open();
 try {
 StringReader srOutDoc = new StringReader(strHtml);
 XMLWorkerHelper.GetInstance().ParseXHtml(pdfWrite, docWorkingDocument, srOutDoc);
 }
 catch (Exception ex) {
 throw ex;
 }
 }
 Response.ContentType = "application/pdf";
 Response.AddHeader("content-disposition", "attachment; filename=" + strFileShortName);
 Response.BinaryWrite(memStrOutput.ToArray());
 }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
 <title></title>
</head>
<body>
 <form id="form1" runat="server">
 <div>
 <asp:Button ID="Button1" runat="server" Text="Generate PDF" OnClick="Button1_Click" />
 </div>
 </form>
</body>
</html>

CSharpTestGen.aspx

This example page shows you how to read the report generated in the CSharpTestReport.aspx page. It then shows you how to first save the PDF file to the Web Server’s hard-drive, and then how to send the file to the client browser using the JavaScript window.open command. The benefit of using a window as compared with a Response.Redirect is that you can control the size and appearance of the newly created browser window.


<%@ Page Language="C#" %>
<%@ Import Namespace="iTextSharp.tool.xml" %>
<%@ Import Namespace="iTextSharp.text.pdf" %>
<%@ Import Namespace="System.IO" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
 protected void Button1_Click(object sender, System.EventArgs e)
 {
 string strHtml = null;
 MemoryStream memStream = new MemoryStream();
 StringWriter strWriter = new StringWriter();
 Server.Execute("CSharpTestReport.aspx", strWriter);
 strHtml = strWriter.ToString();
 strWriter.Close();
 strWriter.Dispose();
 string strFileShortName = "test" + DateTime.Now.Ticks + ".pdf";
 string strFileName = HttpContext.Current.Server.MapPath("reports\\" + strFileShortName);
 iTextSharp.text.Document docWorkingDocument = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4, 1, 1, 0, 0);
 StringReader srdDocToString = null;
 try
 {
 PdfWriter pdfWrite = default(PdfWriter);
 pdfWrite = PdfWriter.GetInstance(docWorkingDocument, new FileStream(strFileName, FileMode.Create));
 srdDocToString = new StringReader(strHtml);
 docWorkingDocument.Open();
 XMLWorkerHelper.GetInstance().ParseXHtml(pdfWrite, docWorkingDocument, srdDocToString);
 }
 catch (Exception ex)
 {
 Response.Write(ex.Message);
 }
 finally
 {
 if ((docWorkingDocument != null))
 {
 docWorkingDocument.Close();
 docWorkingDocument.Dispose();
 }
 if ((srdDocToString != null))
 {
 srdDocToString.Close();
 srdDocToString.Dispose();
 }
 }
 Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "myscript", "window.open('reports/" + strFileShortName + "','_blank','location=0,menubar=0,status=0,titlebar=1,toolbar=1');", true);
 }
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
 <title></title>
</head>
<body>
 <form id="form1" runat="server">
 <div>
 <asp:Button ID="Button1" runat="server" Text="Generate PDF" OnClick="Button1_Click" />
 </div>
 </form>
</body>
</html>

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s