ایجاد PDF فارسی در ASP.NET توسط #C (با استفاده از iTextSharp)

تصویر مهدی
یکی از مهمترین قالبهای ایجاد خروجی، فایلهای PDF هستند. یکی از بهمترین ویژگی این فایلها (که در فرمتهای مشابه کمتر به چشم می خورد) این است که در تمام سیستم ها بدون توجه به نوع سیستم، سیستم عامل، فونتهای نصب شده و ... یکسان دیده میشوند و همچنین در اکثر سیستمها پشتبانی خوبی از آن شده است. با توجه به تنوع سیستمهای کاربران (مخصوصا در برنامه های تحت وب) این ویژگی بسیار بیشتر اهمیت خود را نشان می دهد. بنابراین چندان عجیب نیست که در حال حاضر یکی از محبوبترین فرمتهای ایجاد خروجی (مثلا در گزارشات) فرمت PDF محسوب میشود. کتابخانه های مختلفی برای ایجاد فایلهای PDF وجود دارد. بهترین کتابخانه ای که من برای زبانهای NET. دیده ام، کتابخانه iTextSharp است. این کتابخانه از روی iText که یکی از معروفترین کتابخانه های ایجاد و مدیریت فایلهای PDF است، نوشته شده است. استفاده از این کتابخانه برای کار کردن با زبان فارسی به سادگی امکان پذیر است ولی نیاز به کمی دقت هنگام استفاده است. در اینجا میخواهم روش ساده استفاده از این کتابخانه برای ایجاد صفحات فارسی را توضیح دهم. اولین کاری که در استفاده از این کتابخانه باید انجام دهید، اضافه کردن فایل itextsharp.dll به رفرنس های پروژه است. آخرین نسخه این کتابخانه در زمان نوشتن این متن نسخه 4.1.6.0 است که از اینجا میتوانید آن را دریافت کنید. برای ایجاد فایل PDF از دو فضای نام زیر استفاده می شود:
using iTextSharp.text;
using iTextSharp.text.pdf;
ایجاد یک فایل PDf با استفاده از iTextSharp شامل 5 مرحله است.
  1. ایجاد یک شئ از کلاس Document
  2. ایجاد یک PdfWriter (که به شئ Document گوش میکند و خروجی را بر روی یک stream مینویسد)
  3. باز کردن شئ Document
  4. اضافه کردن محتوای فایل PDF
  5. بستن شئ Document
  6. در ادامه به بررسی این مراحل می پردازیم.

    1 ایجاد شئ Document

    Document doc = new Document();
    

    2 ایجاد PdfWriter

    ورودی های تابع ایجاد کننده، یک شء از کلاس Document است (که در مرحله قبل ساخته شده است) و یک stream است که خروجی بر روی آن نوشته می شود.
    PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream("sample.pdf", FileMode.Create));
    

    3 باز کردن شئ Document

    doc.Open();
    

    4 اضافه کردن محتوای فایل PDF

    برای اضافه کردن یک متن انگلیسی، به سادگی می توان از دستوری مانند دستور زیر استفاده کرد:
    doc.Add(new Paragraph("Hello World"));
    
    ولی برای استفاده از زبان فارسی، کار کمی بیشتر است و باید حتما جهت نوشته ها را به راست به چپ تبدیل کنیم و فونت مناسب انتخاب کنیم. برای تمرکز بیشتر در مراحل، این موارد را در ادامه (بعد از توضیح مراحل) آورده ام.

    5 بستن Document

                doc.Close();
    


    کار با متون فارسی

    همانطور که گفته شد، برای کار با متون فارسی، باید جهت نوشته ها به صورت راست به چپ شود و همچنین فونت مناسب انتخاب شود. یکی از فونتهایی که برای زبان فارسی به خوبی کار میکند و در اکثر سیستمها موجود است، فونت Tahoma است. نکته قابل توجه اینکه این فونت تنها در کامپیوتری که فایل PDF را ایجاد میکند مورد نیاز است و به علت اینکه در فایل PDF گنجانده خواهد شد، در سایر کامپیوترهایی که فایل PDF را مشاده می کنند، نیازی به وجود این فونت نیست. برای استفاده از فونتها، ابتدا باید پوشه حاوی فونتها را به iTextSharp معرفی کنیم و سپس فونت مورد علاقه خود را توسط تابع FontFactory.GetFont انتخاب کنیم. تنها نکته مهم در اینجا استفاده از encoding مناسب است که برای زبان فارسی (یا به طور کلی یونیکد) از IDENTITY_H استفاده می شود. سایر پارامترهای ورودی این تابع مشخص است و نیازی به توضیح اضافی ندارد.
                FontFactory.RegisterDirectories();
                Font fTahoma = FontFactory.GetFont("Tahoma", BaseFont.IDENTITY_H, 12, Font.NORMAL, Color.BLACK);
    
    برای تبدیل جهت نوشته ها، به طور مستقیم نمیتوانیم عمل کنیم و حتما باید نوشته ها را در یک عنصر دیگر که این قابلیت را داشته باشد قرار دهیم. در iTextSharp تنها دو عنصر هستند که این قابلیت را دارند. یکی ColumnText و دیگری PdfPTable است. در این دو عنصر میتوانیم با تنظیم RunDirection، جهت متون را راست به چپ کنیم و متون فارسی را به خوبی در آنها نمایش دهیم. PdfPTable، مشابه جداول در Html کار میکند و ColumnText هم برای ایجاد ستونهای حاوی متون (به صورت یک مستطیل در صفحه) استفاده می شود. در اینجا برای نمونه استفاده از ColumnText نشان داده می شود. ابتدا یک شئ از کلاس ColumnText با استفاده از محتویات شئ PdfWriter ایجاد میکنیم و مقدار RunDirection آن را تنظیم میکنیم. سپس نوع ستون و ویژگیهای آن را تعیین میکنیم. در اینجا من از ستون ساده استفاده کرده ام که پارامترهای ورودی آن، مختصات گوشه های مستطیل است. بعد از آن، بجای اضافه کردن محتویات به طور مستقیم به Document، محتویات را به شئ ایجاد شده از ColumnText اضافه میکنیم (استفاده از فونت مناسب فراموش نشود). در انتها نیز، با استفاده از متد Go، محتویات ColumnText را در Document می نویسیم.
                ColumnText ct = new ColumnText(writer.DirectContent);
                ct.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
                ct.SetSimpleColumn(20, 20, 555, 800);
    
                ct.AddText(new Phrase(txt, fTahoma));
    
                ct.Go();
    


    دانلود کردن PDF ساخته شده در ASP.NET

    در برنامه های تحت وب، بسیار رایج است که بخواهیم فایل ایجاد شده را در سرور، بر روی هارددیسک ننویسیم و آن را در حافظه ایجاد کرده و مستقیما برای دانلود به کلاینت ارسال کنیم. برای این کار می توانیم بجای stream ایجاد شده در مثال بالا، از MemoryStram استفاده کنیم.
                MemoryStream stream = new MemoryStream();
                PdfWriter writer = PdfWriter.GetInstance(doc, stream);
    
    سپس در پایان کار، برای دانلود PDF ایجاد شده در حافظه، ابتدا آن را به یک بافر منتقل میکنیم، و سپس با استفاده از شئ Response محتوای بافر را مستقیما به کلاینت میفرستیم. در صورتی که بخواهیم فایل حتما دانلود شود و در مرورگر کاربر باز نشود، می توانیم با استفاده از هدر content-disposition این موضوع را به مرورگر اطلاع دهیم. در این صورت حتی در صورت نصب بودن پلاگین مشاهده PDF بر روی مرورگر، بازهم صفحه دانلود فایل باز خواهد شد.
                byte[] buffer = stream.GetBuffer();
                stream.Close();
    
                Response.ClearContent();
                Response.AddHeader("content-disposition", "attachment; filename=test.pdf");
                Response.ContentType = "application/pdf";
                Response.OutputStream.Write(buffer, 0, buffer.Length);
                Response.OutputStream.Flush();
                Response.OutputStream.Close();
                Response.End();
    


    مثال

    در پایان یک مثال از مطالب مطرح شده در این مقال ضمیمه شده است. در این ضمیمه، فایل itextsharp.dll نیز وجود دارد و برای اجرای مستقیم آن نیاز به ابزار خاص دیگری ندارد.

    بروزرسانی

    به خاطر درخواست دوستان، یک نمونه ساده از شیوه گرفتن خروجی PDF از GridView اضافه کردم. بزودی یک مثال کاملتر به همراه توضیح کد در یک پست جدید ارایه خواهم داد ولی تا موقعی که فرصت این کار را پیدا کنم، میتوانید از این مثال ساده که در این پست ضمیمه کردم استفاده کنید.

    بروزرسانی 2

    کتابخانه ای برای گرفتن خروجی PDF از GridView تهیه کرده ام که از اینجا میتوانید آن را مشاهده کنید.
    ضمیمهاندازه
    iTextSharpFarsi.zip1.15 مگابایت
    نمونه ساده خروجی PDF از GridView1.09 مگابایت