کتابخانه iTextSharp دارای کلاسی است به نام HTMLWorker که کار تبدیل عناصر HTML را به عناصر متناظر خودش، انجام میدهد. این کلاس در حال حاضر منسوخ شده درنظر گرفته میشود (اینطور توسط نویسندگان آن اعلام شده) و دیگر توسعه نخواهد یافت. بنابراین اگر از HTMLWorker استفاده میکنید با یک کلاس قدیمی که دارای HTML Parser ایی بسیار بدوی است طرف هستید و در کل برای تبدیل محتوای HTML ایی با ساختار بسیار ساده بد نیست؛ اما انتظار زیادی از آن نداشته باشید.
جایگزین کلاس HTMLWorker در این کتابخانه در حال حاضر کتابخانه itextsharp.xmlworker است، که به صورت یک افزونه در کنار کتابخانه اصلی در حال توسعه میباشد. مشکل اصلی این کتابخانه، عدم پشتیبانی از UTF8 و راست به چپ است. بنابراین حداقل به درد کار ما نمیخورد.
راه حل بسیار بهتری برای موضوع اصلی بحث ما وجود دارد و آن هم استفاده از موتور WebKit (همان موتوری که برای مثال در Apple Safari استفاده میشود) برای HTML parsing و سپس تبدیل نتیجه نهایی به PDF است. پروژهای که این مقصود را میسر کرده، wkhtmltopdf نام دارد.
توسط آن به کمک موتور WebKit، کار HTML Parsing انجام شده و سپس برای تبدیل عناصر نهایی به PDF از امکانات کتابخانهای به نام QT استفاده میشود. کیفیت نهایی آن کپی مطابق اصل HTML قابل مشاهده در یک مرورگر است و با یونیکد و زبان فارسی هم مشکلی ندارد.
برای استفاده از این کتابخانهی native در دات نت، شخصی پروژهای را ایجاد کرده است به نام WkHtmlToXSharp که محصور کنندهی wkhtmltopdf میباشد. در ادامه به نحوه استفاده از آن خواهیم پرداخت:
الف) دریافت پروژه WkHtmlToXSharp
پروژه WkHtmlToXSharp را از آدرس زیر میتوانید دریافت کنید.
این پروژه به همراه فایلهای کامپایل شده نهایی wkhtmltopdf نیز میباشد و حجمی حدود 40 مگ دارد. به علاوه فعلا نسخه 32 بیتی آن در دسترس است. بنابراین باید دقت داشت که نباید تنظیمات پروژه دات نت خود را بر روی Any CPU قرار دهیم، زیرا در این حالت برنامه شما در یک سیستم 64 بیتی بلافاصله کرش خواهد کرد. تنظیمات target platform پروژه دات نتی ما حتما باید بر روی X86 تنظیم شود.
ب) پس از دریافت این پروژه و افزودن ارجاعی به اسمبلی WkHtmlToXSharp.dll، استفاده از آن به نحو زیر میباشد:
using System.IO; using WkHtmlToXSharp; using System; namespace Test2 { public class WkHtmlToXSharpTest { public static void ConvertHtmlStringToPdfTest() { using (var wk = new MultiplexingConverter()) { wk.Begin += (s, e) => Console.WriteLine("Conversion begin, phase count: {0}", e.Value); wk.Error += (s, e) => Console.WriteLine(e.Value); wk.Warning += (s, e) => Console.WriteLine(e.Value); wk.PhaseChanged += (s, e) => Console.WriteLine("PhaseChanged: {0} - {1}", e.Value, e.Value2); wk.ProgressChanged += (s, e) => Console.WriteLine("ProgressChanged: {0} - {1}", e.Value, e.Value2); wk.Finished += (s, e) => Console.WriteLine("Finished: {0}", e.Value ? "success" : "failed!"); wk.GlobalSettings.Margin.Top = "0cm"; wk.GlobalSettings.Margin.Bottom = "0cm"; wk.GlobalSettings.Margin.Left = "0cm"; wk.GlobalSettings.Margin.Right = "0cm"; wk.ObjectSettings.Web.EnablePlugins = false; wk.ObjectSettings.Web.EnableJavascript = false; wk.ObjectSettings.Load.Proxy = "none"; var htmlString = File.ReadAllText(@"c:\page.xhtml"); var tmp = wk.Convert(htmlString); File.WriteAllBytes(@"tst.pdf", tmp); } } } }
کار با وهله سازی از کلاس MultiplexingConverter شروع میشود. اگر علاقمند باشید که درصد پیشرفت کار به همراه خطاهای احتمالی پردازشی را ملاحظه کنید میتوان از رخدادگردانهایی مانند ProgressChanged و Error استفاده نمائید که نمونهای از آن در کد فوق بکارگرفته شده است.
تبدیل HTML به PDF آنچنان تنظیمات خاصی ندارد زیرا فرض بر این است که قرار است از همان تنظیمات اصلی HTML مورد نظر استفاده گردد. اما اگر نیاز به تنظیمات بیشتری وجود داشت، برای مثال به کمک GlobalSettings آن میتوان حاشیههای صفحات فایل نهایی تولیدی را تنظیم کرد.
موتور WebKit با توجه به اینکه موتور یک مرورگر است، امکان پردازش جاوا اسکریپت را هم دارد. بنابراین اگر قصد استفاده از آنرا نداشتید میتوان خاصیت ObjectSettings.Web.EnableJavascript را به false مقدار دهی کرد.
کار اصلی، در متد Convert انجام میشود. در اینجا میتوان یک رشته را که حاوی فایل HTML مورد نظر است به آن ارسال کرد و نتیجه نهایی، آرایهای از بایتها، حاوی فایل باینری PDF تولیدی است.
روش دیگر استفاده از این کتابخانه، مقدار دهی wk.ObjectSettings.Page میباشد. در اینجا میتوان Url یک صفحه اینترنتی را مشخص ساخت. در این حالت دیگر نیازی نیست تا به متد Convert پارامتری را ارسال کرد. میتوان از overload بدون پارامتر آن استفاده نمود.
یک نکته:
اگر میخواهید زبان فارسی را توسط این کتابخانه به درستی پردازش کنید، نیاز است حتما یک سطر زیر را به header فایل html خود اضافه نمائید:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />