Why iText?
Updated 27-12-2015 - Added a
bullet regarding using iTextSharp with a medium trust shared web hosting
provider.
How many times have you been asked to generate a report in
an open file format such as PDF? iTextSharp,
a free C# PDF library ported from the Java-PDF Library iText, gives you a nice option.
Important
/ Breaking Changes
- For some
reason a lot of people using iText[Sharp] primarily want to use the
library for HTML to PDF conversion. It also seems thepercentage of .NET developers is higher. I
completely agree with the comment by Mark Storer, an iText committer, at the
bottom of that page. With that being said, the development team is
shifting their their efforts from the HTMLWorker class (traditionally used to
convert HTML to PDF) to XMLWorker, which was released on 2011-06-08. Here are some
useful links:
- XMLWorker
API
- XMLWorker Documentation - a really
rough work in progress.
- XMLWorker
Demo
- iTextSharp XMLWorker - it's a separate download
And you must take
into consideration that iText[Sharp] has never made HTML/XML
to PDF conversion one of it's main goals or selling points. Whether you
use HTMLWorker or XMLWorker, DO
NOT EXPECT A FULL-BLOWN CONVERSION TOOL, YOU WILL BE DISSAPOINTED!
- iText
5.0.1.1, released on 2010-04-05, introduced Generics (System.Collections.Generic Namespace) in
many classes. Prior versions used collections from the System.Collections Namespace.
- Due to a lazy, stupid question on the mailing list,
the source code for all iTextSharp versions prior to 5.0
that fall under the GNU Lesser General Public License were
removed on 2011-03-28 from the SourceForge source code / file download page.
If you think that's a harsh statement, the tutorial (code) referenced by
the OP was clearly dated
as almost SIX YEARS OLD.
- iText 5.0.6,
released on 2011-02-18, now supports the IDisposable interface for all classes
that implement the IDocListener interface or inherit from
the PdfStamper class. So if you prefer, creating a PDF is now
a four-step process - just add a using statement and you can forget all
those Close() calls. Another simple specific example using
both Document and PdfStamper.
- The Table and HeaderFooter objects
in the original code snippets (written sometime in 2007) are two of the
many classes removed in iText 5.0.0, which was released
on 2009-12-07.
- For those
still using an older version of iText[Sharp], a stand-alone example is
included in the section below titled "Example
for iTextSharp Versions Less Than 5.XX"; the F/OSS license
was also changed from MPL/LGPL to AGPL starting with iText 5.0.0. Here is
a mailing list thread that describes some of the reasons
for the license change. But a word of advice - you're better
off going with the newer 5.X.x branches.
Getting
Started
In
general creating a PDF with iText[Sharp] is a five-step process:
- Instantiate
a Document object.
- Get an instance of the PdfWriter object.
- Open the Document instance.
- Add content to the Document instance.
- Close the document. As explained above you
can omit step 5 from iTextSharp 5.0.6.
The following example shows how to:
- Create a
centered, single-page document header. If you need to add
page headers to all pages of your document see Adding
PDF Page Headers, which shows the recommended method to add
page headers using the PdfPageEventHelper class.
- Add a
center-aligned image to the document.
- Add a center-aligned
paragraph to the document.
- Add tabular
formatted data to the document.
iTextSharp
Versions 5 and Above
Creating our PDF going from step 1 through 4. Uncomment where
specified (Document using statement) if using
anything less than 5.0.6:
/*
* step 1
*
* __ONLY__ if using version >= 5.0.6
* see commented section directly below
*
*/
using (Document doc = new Document()) {
/*
* uncomment this line __AND__ comment out line
above if you're
* using version < 5.0.6
*
* Document doc = new Document();
*
*/
// step 2
PdfWriter writer =
PdfWriter.GetInstance(doc, Response.OutputStream);
// step 3
doc.Open();
// step 4
/*
* create document header; shows GMT time when
PDF created.
* HeaderFooter class removed in iText 5.0.0,
so we instead write
* content to an **absolute** position on the
document
*/
Rectangle page = doc.PageSize;
PdfPTable head = new PdfPTable(1);
head.TotalWidth = page.Width;
Phrase phrase = new Phrase(
DateTime.UtcNow.ToString("yyyy-MM-dd
HH:mm:ss") + " GMT",
new Font(Font.FontFamily.COURIER, 8)
);
PdfPCell c = new PdfPCell(phrase);
c.Border = Rectangle.NO_BORDER;
c.VerticalAlignment = Element.ALIGN_TOP;
c.HorizontalAlignment = Element.ALIGN_CENTER;
head.AddCell(c);
head.WriteSelectedRows(
// first/last row; -1 writes all rows
0, -1,
// left offset
0,
// ** bottom** yPos of the table
page.Height - doc.TopMargin +
head.TotalHeight + 20,
writer.DirectContent
);
/*
* add image to document
*/
Image gif = Image.GetInstance(
Request.MapPath("~/kyouyuu/image/kuujinbo2.gif")
);
gif.Alignment = Image.MIDDLE_ALIGN;
// downsize the image by
specified percentage
gif.ScalePercent(50f);
doc.Add(gif);
/*
* add tabular data
*/
// table heading
Paragraph p = new Paragraph("US
Presidents Born in " + _state);
p.Alignment = 1;
doc.Add(p);
// table data, see code
snippet following this one
doc.Add( _stateTable() );
/*
* step 5 is __REQUIRED__ if using version <
5.0.6; uncomment Close()
* below and comment out the bracket below!
*
* doc.Close();
*
*/
}
Creating a simple table is easy; query the database (data access
code omitted) and add each rowset to the table in the PDF:
// add a table to the PDF
document
private PdfPTable
_stateTable() {
string[] col = { "No.",
"Name", "City" };
PdfPTable table = new PdfPTable(3);
/*
* default table width =>
80%
*/
table.WidthPercentage = 100;
// then set the column's
__relative__ widths
table.SetWidths(new Single[] {1, 5, 4});
/*
* by default tables
'collapse' on surrounding elements,
* so you need to explicitly
add spacing
*/
table.SpacingBefore = 10;
for (int i = 0; i < col.Length; ++i) {
PdfPCell cell = new PdfPCell(new
Phrase(col[i]));
cell.BackgroundColor = new BaseColor(204,
204, 204);
table.AddCell(cell);
}
// !! database code omitted
!!
// r.Read is the DbDataReader
for whatever flavor
// of database you're
connecting to; we're iterating
// over the results returned
from the database and
// adding rows to the table
in the PDF
while (r.Read()) {
table.AddCell(r["id"].ToString());
table.AddCell(r["name"].ToString());
table.AddCell(r["city"].ToString());
}
}
return table;
}
Here's a stand-alone working HTTP handler that works with 4.1.6.
<%@ WebHandler Language='C#'
Class='itext' %>
/*
* example ONLY WORKS for iTextSharp <
5.0.0;
* as of 2011-03-28 source code for older
versions __NOT__ available
*/
using System;
using System.Web;
using iTextSharp.text;
using iTextSharp.text.pdf;
public class itext : IHttpHandler
{
//
===========================================================================
public void ProcessRequest (HttpContext
context) {
HttpResponse Response = context.Response;
Response.ContentType =
"application/pdf";
Response.AppendHeader(
"Content-Disposition",
"attachment;
filename=itext.pdf"
);
// step 1
Document doc = new Document();
// step 2
PdfWriter writer =
PdfWriter.GetInstance(doc, Response.OutputStream);
/*
* create document header; shows GMT time when
PDF created.
* set header [1] text [2] font style
*/
Phrase phrase = new Phrase(
DateTime.UtcNow.ToString("yyyy-MM-dd
HH:mm:ss") + " GMT",
new Font(Font.COURIER, 8)
);
HeaderFooter header = new HeaderFooter
(phrase, false);
// top & bottom borders
on by default
header.Border = Rectangle.NO_BORDER;
// center header
header.Alignment = 1;
/*
* HeaderFooter => add header __before__
opening document
*/
doc.Header = header;
// step 3
doc.Open();
// step 4
/*
* add image to document
*/
Image gif = Image.GetInstance(
"http://kuujinbo.info/kyouyuu/image/kuujinbo2.gif"
);
gif.Alignment = Image.MIDDLE_ALIGN;
// downsize the image by
specified percentage
gif.ScalePercent(50f);
doc.Add(gif);
/*
* add tabular data
*/
// table heading
Paragraph p = new Paragraph("Table
Heading");
p.Alignment = 1;
doc.Add(p);
// table 'data'
Table table = new Table(3);
table.BorderWidth = 1;
table.BorderColor = new Color(0, 0, 255);
table.Padding = 4;
table.Width = 100;
// set *column* widths
float[] widths = {.3f, .5f, .4f};
table.Widths = widths;
string[] col = {"COL 1",
"COL 2", "COL 3"};
for (int i = 0; i < col.Length; ++i) {
Cell cell = new Cell(col[i]);
cell.Header = true;
cell.BackgroundColor = new Color(204,
204, 204);
table.AddCell(cell);
}
table.EndHeaders();
for (int i = 1; i < 5; ++i) {
for (int j = 0; j < col.Length; ++j) {
table.AddCell(string.Format(
"Row {0}, Cell {1}",
i, j + 1
));
}
}
doc.Add(table);
// step 5
doc.Close();
}
public bool IsReusable {
get { return false; }
}
//
===========================================================================
}
- If you don't
own the
book, see what some of the the
differences between iText and iTextSharp. It will help when you
look through the source code, since the API
is only available in Java.
- Occasionally
questions pop up on the mailing list or one of the many programming forums
about problems with a corrupt PDF generated when working with a MemoryStream. It's usually a result of
calling MemoryStream.GetBuffer(). See this mailing list postexplaining why
you should be calling MemoryStream.ToArray() instead. In most
cases you DO NOT need to use a MemoryStream to
create the PDF! I've lost track of how many programming forum posts and
web sites I've seen showing examples usingMemoryStream. If you're a
web developer, you have access to Response.OutputStream, so use it! And if
you're a desktop application developer you can use any Stream of your choice.
- If your web
site is on a shared web hosting service and only
allows Medium Trust, you need to download the source code and build it yourself.
Don't
forget to set the correct Content-Type before you send the PDF
stream if you're running a web application:
Response.ContentType =
"application/pdf";
// [optional]
Response.AddHeader(
"Content-Disposition",
"attachment; filename=itext.pdf"
);
No comments:
Write comments