۱۳۹۰/۰۸/۲۹

اضافه كردن پيوست به فايل‌هاي PDF با استفاده از iTextSharp


فايل PDF موجود عجيب و غريبي است. مي‌شود به آن فايل پيوست اضافه كرد. مثلا اگر يك راهنماي آموزشي را با فرمت PDF تهيه مي‌كنيد، لازم نيست تا فايل‌هاي مرتبط با آن‌را جداگانه ارائه دهيد. مي‌شود تمام اين‌ها را داخل همان فايل PDF مدفون كرد. روش انجام اينكار به كمك iTextSharp ساده است اما چند نكته را نيز به همراه دارد:

using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace PDFAttachment
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var pdfDoc = new Document(PageSize.A4))
            {
                var pdfWriter = PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));                
                pdfDoc.Open();

                pdfDoc.Add(new Phrase("Test"));

                var fs = PdfFileSpecification.FileEmbedded(pdfWriter, @"C:\path\logo.png", "logo.png", null);
                pdfWriter.AddFileAttachment("توضيحات",fs);
            }

            Process.Start("Test.pdf");
        }
    }
}

در ساده‌ترين حالت ممكن، با استفاده از متد AddFileAttachmen شيء PdfWriter مي‌توان پيوستي را به يك فايل PDF در حال توليد اضافه كرد. اگر به فايل نهايي مراجعه كنيم و همچنين قسمت attachments را هم دستي در Adobe reader انتخاب نمائيم، شكل زير حاصل خواهد شد:


روش متداول بكارگرفته شده دو مشكل را به همراه دارد:
  • قسمت modified مقدار دهي نشده است.
  • پنل مربوط به پيوست‌ها بايد دستي باز شود.

نحوه مقدار دهي ستون modified پس از تعريف يك PdfDictionary و قرار دادن PdfName.MODDATE در آن، به صورت زير است:

using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace PDFAttachment
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var pdfDoc = new Document(PageSize.A4))
            {
                var pdfWriter = PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));                
                pdfDoc.Open();

                pdfDoc.Add(new Phrase("Test"));

                var filePath = @"C:\path\logo.png";
                var fileInfo = new FileInfo(filePath);
                var pdfDictionary = new PdfDictionary();
                pdfDictionary.Put(PdfName.MODDATE, new PdfDate(fileInfo.LastWriteTime));
                var fs = PdfFileSpecification.FileEmbedded(pdfWriter, filePath, fileInfo.Name, null, true, null, pdfDictionary);
                pdfWriter.AddFileAttachment("توضيحات", fs);
            }

            Process.Start("Test.pdf");
        }
    }
}

كه اينبار خروجي زير را به همراه دارد:


و براي نمايش خودكار پنل پيوست‌ها در Adobe reader به طوري كه كاربر نهايي متوجه وجود اين فايل‌هاي پيوست شده گردد، مي‌توان ViewerPreferences شيء pdfWriter را مقدار دهي نمود:

pdfWriter.ViewerPreferences = PdfWriter.PageModeUseAttachments;

در مورد فايل‌هاي موجود چطور؟ آيا مي‌توان به يك فايل PDF از پيش تهيه شده هم فايل پيوست كرد؟
پاسخ: بله. بايد از امكانات شيء PdfReader استفاده كرد:

using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace PDFAttachment
{
    class Program
    {
        static void Main(string[] args)
        {
            var reader = new PdfReader("Test.pdf");
            using (var stamper = new PdfStamper(reader, new FileStream("newTest.pdf", FileMode.Create)))
            {
                var filePath = @"C:\path\logo.png";
                addAttachment(stamper, filePath, "توضيحات");
                stamper.Close();
            }

            Process.Start("newTest.pdf");
        }

        private static void addAttachment(PdfStamper stamper, string filePath, string description)
        {
            var fileInfo = new FileInfo(filePath);
            var pdfDictionary = new PdfDictionary();
            pdfDictionary.Put(PdfName.MODDATE, new PdfDate(fileInfo.LastWriteTime));
            var pdfWriter = stamper.Writer;
            var fs = PdfFileSpecification.FileEmbedded(pdfWriter, filePath, fileInfo.Name, null, true, null, pdfDictionary);
            stamper.AddFileAttachment(description, fs);
        }
    }
}

در اينجا به كمك كلاس PdfReader، يك فايل موجود خوانده شده و سپس با استفاده از امكانات كلاس PdfStamper كه خاصيت Writer آن همان pdfWriter است مي‌توان فايل مورد نظر را به فايل موجود افزود.