Tag: iTextSharp

  • เรียนรู้เบื้องต้นกับการใส่ลายน้ำ(Watermark)ให้กับเอกสาร PDF ของเราด้วย iTextSharp

                   ในบทความนี้เราก็ยังคงอยู่กับเรื่องการทำภาพลายน้ำอย่างต่อเนื่องจาก EP. ที่แล้วที่พูดถึงการทำข้อความลายน้ำบนภาพที่เราทำการอัพโหลด ถ้าใครยังไม่ได้อ่านสามารถตามไปอ่านกันได้ ที่นี่ นะคะแต่สำหรับ EP. นี้เราจะขอเปลี่ยนบรรยากาศไปทำ ลายน้ำบนไฟล์ PDF โดยใช้เครื่องมือ iTextSharp กันบ้าง เผื่อว่าผู้อ่านบางท่านที่อาจจะกำลังใช้งาน iTextSharp ในการจัดทำไฟล์ PDF อยู่พอดี และอยากจะลองใส่ลายน้ำให้กับงานเอกสารของท่านดูบ้าง จะได้สามารถนำวิธีการนี้ไปประยุกต์ใช้กับงานของตนได้ไม่ทางใดก็ทางหนึ่งนะคะ โดยตัวอย่างที่จะนำมาแนะนำกันจะมีทั้งแบบลายน้ำที่เป็นข้อความ และลายน้ำที่เป็นภาพค่ะ นอกจากนี้ก็ยังมีทั้งแบบที่เป็นการทำภาพลายน้ำทับไฟล์เดิมที่มีอยู่ และแบบที่ทำภาพลายน้ำและบันทึกเป็นไฟล์ใหม่ค่ะ ผู้อ่านจะได้ลองในหลายๆวิธี และสามารถเลือกไปปรับใช้ให้เหมาะกับงานของแต่ละท่านได้เพื่อไม่ให้เป็นการเสียเวลา งั้นเรามาเริ่มทำภาพลายน้ำบนงานเอกสาร PDF ของเรากันเลยดีกว่าค่ะ

    แบบที่ 1 : การสร้างลายน้ำแบบข้อความ ซึ่งวิธีการนี้ จะมีการทำ Template ต้นฉบับของลายน้ำแบบข้อความไว้ก่อน และเมื่อต้องการทำไฟล์ลายน้ำ จะต้องทำการอ่านไฟล์ลายน้ำจากต้นแบบมาจัดทำลายน้ำบนไฟล์ที่ต้องการได้ ดังนี้ค่ะ

    1.1 ระบุ Library เพิ่มเติม

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

    1.2 สร้างเมธอดในการสร้าง Template ลายน้ำต้นฉบับ เพื่อใช้ในการทำลายน้ำให้กับไฟล์ PDF ที่ต้องการ

            ////กรณียังไม่เคยสร้างหรือมี Template มาก่อน ให้เรียกใช้งาน CreateTemplate("ข้อความที่ต้องการให้แสดงในเทมเพลต",พาธที่จะสร้างไฟล์เทมเพลตดังกล่าว) 
            public void CreateTemplate(string watermarkText, string targetFileName)
            {
                var document = new Document();
    
                ////ระบุพาธที่ต้องการสร้างไฟล์เทมเพลต
                var pdfWriter = PdfWriter.GetInstance(document, new FileStream(targetFileName, FileMode.Create));
                ///ระบุค่าต่างๆเกี่ยวกับตัวอักษรที่จะแสดงผลในเทมเพลตลายน้ำที่สร้างขึ้น
                var font = new Font(Font.FontFamily.HELVETICA, 60, Font.NORMAL, BaseColor.LIGHT_GRAY);
                document.Open();
    
                ////ระบุค่าข้อความ และค่าต่างๆให้กับลายน้ำที่ต้องการ
                ColumnText.ShowTextAligned(pdfWriter.DirectContent, Element.ALIGN_CENTER, new Phrase(watermarkText, font), 300, 400, 45);
                document.Close();
            }

    ตัวอย่าง ไฟล์ PDF ของ Template ลายน้ำที่ได้จากการเรียกใช้งานเมธอด CreateTemplate ข้างต้น

    1.3 สร้างเมธอดในการจัดทำลายน้ำข้อความให้กับไฟล์ PDF จาก template ลายน้ำต้นฉบับ

    public void AddTextWatermark(string sourceFilePath, string watermarkTemplatePath, string targetFilePath)
            {
                ///ระบุพาธไฟล์ต้นทางที่ต้องการทำข้อความลายน้ำ
                var pdfReaderSource = new PdfReader(sourceFilePath);
                ///ระบุพาธไฟล์ปลายทางที่ต้องการบันทึกไฟล์แบบมีลายน้ำ
                var pdfStamper = new PdfStamper(pdfReaderSource, new FileStream(targetFilePath, FileMode.Create));
    
                ///ระบุพาธของไฟล์ต้นแบบลายน้ำที่จัดทำไว้
                var pdfReaderTemplate = new PdfReader(watermarkTemplatePath);
                var page = pdfStamper.GetImportedPage(pdfReaderTemplate, 1);
    
                ///ทำการวนลูปเพื่อทำลายน้ำให้กับไฟล์ PDF ทีละหน้า
                for (var i = 0; i < pdfReaderSource.NumberOfPages; i++)
                {
                    ///ระบุตำแหน่งในการแสดงผลลายน้ำกับเนื้อหาในไฟล์ PDF กรณีนี้คือวางไว้ใต้เนื้อหา แต่หากต้องการให้อยู่บนเนื้อหาให้เปลี่ยนเป็น GetOverContent แทน 
                    var content = pdfStamper.GetUnderContent(i + 1);
                    content.AddTemplate(page, 0, 0);
                }
    
                pdfStamper.Close();
                pdfReaderTemplate.Close();
            }

    1.4 เรียกใช้งานเมธอดเพื่อทำลายน้ำให้กับไฟล์ PDF ที่ต้องการ(กรณีนี้สมมุติให้เป็นการกดปุ่มเพื่อเรียกใช้งานเมธอดดังกล่าว)

     protected void btnGenWatermark_Click(object sender, EventArgs e)
            {
                 ////กำหนด Path ของไฟล์ PDF ต้นทางที่ต้องการทำลายน้ำ กรณีที่ gen จาก iTextSharp สามารถนำมาประยุกต์ใช้โดยเอาพาธดังกล่าวมาใช้เป็น strSourcePath ได้เลย
                string strSourcePath = HttpContext.Current.Server.MapPath("~/PDF/File/PDFDocument.pdf");
    
                 ////สร้างตัวแปรชื่อไฟล์ PDF ที่จะบันทึกใหม่ในชื่อตัวแปร genName
                string genName = Guid.NewGuid().ToString() + ".pdf";
    
                 ////กรณียังไม่เคยสร้างหรือมี Template มาก่อนให้เรียกใช้งาน CreateTemplate("ข้อความที่ต้องการให้แสดงในเทมเพลต",templatePath)  ทั้งชื่อไฟล์เทมเพลตใหม่ที่จะบันทึก
                string templatePath = HttpContext.Current.Server.MapPath("~/PDF/TemplateWatermarkPDF/" + genName);
    
                 ////ระบุพาธปลายทางที่ต้องการบันทึกไฟล์แบบมีลายน้ำพร้อมทั้งชื่อไฟล์ใหม่ที่จะบันทึก
                string targetPath = HttpContext.Current.Server.MapPath("~/PDF/WatermarkPDF/" + genName);
    
                 ////ตรวจสอบว่ามีไฟล์ดังกล่าวอยู่จริงตามที่อยู่ที่ระบุไว้หรือไม่
                if( File.Exists(strSourcePath))
                { 
                     ////กรณียังไม่เคยสร้างหรือมี Template มาก่อน ให้เรียกใช้งาน CreateTemplate("ข้อความที่ต้องการให้แสดงในเทมเพลต",พาธที่จะสร้างไฟล์เทมเพลตดังกล่าว) 
                    CreateTemplate("Copyrights (c) 2023", templatePath);
    
                     ////เรียกใช้งานเมธอดในการสร้างข้อความลายน้ำตามเทมเพลตที่มี(ตามพาธที่ระบุ) โดยส่งค่าที่อยู่ของไฟล์ต้นทาง พาธเทมเพลตที่ต้องการทำลายน้ำ และพาธปลายทางที่ต้องการบันทึกไฟล์แบบมีลายน้ำ
                    AddTextWatermark(strSourcePath, templatePath, targetPath);
                }
            }

    ตัวอย่างผลลัพธ์

    หมายเหตุ : 

    1. บางครั้งอาจพบว่าการใช้ GetUnderContent อาจทำให้ข้อความลายน้ำโดนเนื้อหาบดบังได้ในบางกรณี จนอาจจะต้องใช้ GetOverContent แทนดังเช่นตัวอย่างต่อไปนี้ 

    แต่สำหรับเนื้อหาในไฟล์ PDF โดยทั่วไปแล้ว สามารถใช้งาน GetUnderContent ได้ตามปกติ เพื่อไม่ให้ข้อความลายน้ำบดบังเนื้อหาในเอกสาร

    แบบที่ 2 การสร้างลายน้ำแบบรูปภาพให้กับเอกสาร PDF โดยจะขอยกตัวอย่างให้ดู 2 แบบนะคะ คือแบบที่สร้างลายน้ำบนไฟล์ PDF ใหม่ และแบบที่สร้างลายน้ำบนไฟล์ต้นทางเดิมค่ะ 

    2.1 แบบสร้างลายน้ำบนไฟล์ใหม่ โดยการสร้างเมธอด AddImageWatermark

        public void AddImageWatermark(string sourceFilePath, string watermarkImagePath, string targetFilePath)
            {
                ///ระบุพาธไฟล์ต้นทางที่ต้องการทำภาพลายน้ำ
                var pdfReader = new PdfReader(sourceFilePath);
    
                ///ระบุพาธไฟล์ปลายทางที่ต้องการบันทึกไฟล์แบบมีภาพลายน้ำ
                var pdfStamper = new PdfStamper(pdfReader, new FileStream(targetFilePath, FileMode.Create));
    
                ///ระบุพาธของไฟล์ภาพที่ต้องการนำมาทำภาพลายน้ำ
                var image = iTextSharp.text.Image.GetInstance(watermarkImagePath);
                image.SetAbsolutePosition(200, 400);
    
                ///ทำการวนลูปเพื่อทำภาพลายน้ำให้กับไฟล์ PDF ทีละหน้า
                for (var i = 0; i < pdfReader.NumberOfPages; i++)
                {
                    var content = pdfStamper.GetUnderContent(i + 1);
                    content.AddImage(image);
                }
    
                pdfStamper.Close();
            }

    วิธีเรียกใช้งาน (กรณีนี้สมมุติให้เป็นการกดปุ่มเพื่อเรียกใช้งานเมธอดดังกล่าว)

            protected void btnGenWatermark_Click(object sender, EventArgs e)
            {
                ////กำหนด Path ของไฟล์ภาพที่ต้องการทำลายน้ำ
                string strWaterMark = HttpContext.Current.Server.MapPath("~/images/clientpreview.png");
                
    ////ระบุ Path ของไฟล์ PDF ต้นทางที่ต้องการทำลายน้ำ string strSourcePath = HttpContext.Current.Server.MapPath("~/PDF/File/job_apply_form.pdf");
    ////สร้างตัวแปรชื่อไฟล์ PDF ที่จะบันทึกใหม่ในชื่อตัวแปร genName string genName = Guid.NewGuid().ToString() + ".pdf";
    ////ระบุพาธปลายทางที่ต้องการบันทึกไฟล์แบบมีลายน้ำพร้อมทั้งชื่อไฟล์ใหม่ที่จะบันทึก string targetPath = HttpContext.Current.Server.MapPath("~/PDF/WatermarkPDF/" + genName);
    ////ตรวจสอบว่ามีไฟล์ภาพลายน้ำ และไฟล์ PDF ต้นทางดังกล่าวอยู่จริงตามที่อยู่ที่ระบุไว้หรือไม่ if (File.Exists(strWaterMark) && File.Exists(strSourcePath)) { AddImageWatermark(strSourcePath, strWaterMark, targetPath); } }

    2.2 แบบสร้างลายน้ำบนไฟล์เดิม โดยการสร้างเมธอด AddImageWatermarkInExistingFile

     private void AddImageWatermarkInExistingFile(string sourceFilePath,string watermarkImagePath )
            {
                 ///อ่านค่าจากพาธไฟล์ต้นทางที่ต้องการทำภาพลายน้ำ
                byte[] bytes = File.ReadAllBytes(sourceFilePath);
    
                 ///ระบุพาธของไฟล์ภาพที่ต้องการนำมาทำภาพลายน้ำ
                var img = iTextSharp.text.Image.GetInstance(watermarkImagePath);
    
                img.SetAbsolutePosition(200, 400);
                PdfContentByte waterMark;
    
                using (MemoryStream stream = new MemoryStream())
                {
                     ///ทำภาพลายน้ำในไฟล์ต้นทางที่ต้องการทำภาพลายน้ำ
                    PdfReader reader = new PdfReader(bytes);
                    using (PdfStamper stamper = new PdfStamper(reader, stream))
                    {
                        ///ทำการวนลูปเพื่อทำภาพลายน้ำให้กับไฟล์ PDF ทีละหน้า
                        int pages = reader.NumberOfPages;
                        for (int i = 1; i <= pages; i++)
                        {
                            waterMark = stamper.GetUnderContent(i);
                            waterMark.AddImage(img);
                        }
                    }
                    bytes = stream.ToArray();
                }
                File.WriteAllBytes(sourceFilePath, bytes);
            }

    วิธีเรียกใช้งาน (กรณีนี้สมมุติให้เป็นการกดปุ่มเพื่อเรียกใช้งานเมธอดดังกล่าว)

            protected void btnGenWatermark_Click(object sender, EventArgs e)
            {
                ////กำหนด Path ของไฟล์ภาพที่ต้องการทำลายน้ำ
                string strWaterMark = HttpContext.Current.Server.MapPath("~/images/clientpreview.png");
    
                ////ระบุ Path ของไฟล์ PDF ต้นทางที่ต้องการทำลายน้ำ
                string strSourcePath = HttpContext.Current.Server.MapPath("~/PDF/File/job_apply_form.pdf");
    
                ////สร้างตัวแปรชื่อไฟล์ PDF ที่จะบันทึกใหม่ในชื่อตัวแปร genName
                string genName = Guid.NewGuid().ToString() + ".pdf";
    
                 ////ตรวจสอบว่ามีไฟล์ภาพลายน้ำ และไฟล์ PDF ต้นทางดังกล่าวอยู่จริงตามที่อยู่ที่ระบุไว้หรือไม่
                if (File.Exists(strWaterMark) && File.Exists(strSourcePath))
                {
                    AddImageWatermarkInExistingFile(strSourcePath,strWaterMark);
                 }
            }
    

    ตัวอย่างผลลัพธ์

    หมายเหตุ :
    1. ทั้งสองวิธีข้างต้นจะให้ผลลัพธ์ของภาพลายน้ำแบบเดียวกัน แต่ต่างกันตรงที่ไฟล์ที่บันทึกภาพลายน้ำ โดยแบบแรกจะสร้างเป็นไฟล์ใหม่ แต่แบบที่สองจะบันทึกลงบนไฟล์เดิม

    2. ในการใช้ภาพทำภาพลายน้ำ อาจจะต้องระวังเกี่ยวกับขนาดภาพที่นำมาใช้ในการแสดงผล และอาจต้องทดสอบการจัดวางตำแหน่งของภาพ เพื่อให้ภาพลายน้ำดังกล่าวออกมาสวยงาม และตรงกับความต้องการในการใช้งาน เพราะหากใช้ภาพที่ใหญ่หรือเล็กเกินไป อาจทำให้ไม่เหมาะกับการนำมาใช้งานได้

               ซึ่งทั้งหมดนี้ก็เป็นเพียงวิธีเบื้องต้นในการสร้างภาพลายน้ำด้วย iTextSharp เท่านั้น เราอาจจะต้องลองผิดลองถูก ประยุกต์วิธีการนำไปใช้ไปด้วยกัน และหวังว่าบทความนี้จะเป็นประโยชน์กับผู้อ่านเพื่อให้แต่ละท่านสามารถนำวิธีดังกล่าวไปประยุกต์ใช้เพิ่มเติมกับงานพัฒนาที่ท่านกำลังทำอยู่ หรือหากผู้อ่านท่านใดมีข้อเสนอแนะสามารถให้คำแนะนำมาได้นะคะ ทางเรายินดีรับฟังทุกข้อเสนอแนะ เพื่อเป็นการต่อยอดความรู้ร่วมกันนะคะ แล้วพบกันใหม่ในบทความหน้า และขอบคุณที่ติดตามกันนะคะ ^^

    แหล่งอ้างอิง

  • วิธีการรวมไฟล์ pdf หลายไฟล์และรูปภาพมาแสดงในครั้งเดียวด้วย iTextSharp (#C)

              ที่มาของบทความนี้ เนื่องด้วยงานที่ผู้เขียนได้รับมอบหมายให้พัฒนาอยู่นั้น มีส่วนหนึ่งที่เป็นการแนบไฟล์เอกสาร/หลักฐานทั้งในรูปแบบไฟล์ PDF และรูปภาพ เข้ามาจากผู้ใช้งาน ซึ่งเอกสารเหล่านี้จะต้องมีส่วนของการแสดงผลให้ทางฝั่งเจ้าหน้าที่ทำการตรวจสอบเอกสาร/หลักฐานดังกล่าวด้วย โดยเดิมทีจะมีการแสดงผลแยกเป็นรายการให้เจ้าหน้าที่เพื่อคลิกดูรายละเอียดทีละรายการ ดังภาพ

              ซึ่งในการทำงานจริงแล้วนั้นพบว่า การตรวจสอบเอกสาร/หลักฐานต่างๆที่ผู้ใช้แนบมาสามารถทำได้ยากและต้องใช้เวลา เนื่องจากเจ้าหน้าที่จะต้องทำการคลิกดูรายละเอียด/ดาวน์โหลดไฟล์คราวละ 1 ไฟล์เพื่อตรวจสอบ ซึ่งไฟล์จะแยกกันอยู่ หากต้องการดาวน์โหลดก็ต้องดาวน์โหลดทีละไฟล์ ดังภาพ

    จึงเป็นที่มาของการค้นหาวิธีการแสดงผลไฟล์ทั้งหมดให้เจ้าหน้าที่สามารถตรวจสอบและดูรายละเอียดข้อมูลเอกสารไฟล์แนบได้ในคราวเดียว ซึ่งผู้เขียนก็ได้นำวิธีการดังกล่าวมาแบ่งปันให้กับผู้อ่านที่มีความสนใจและประสบปัญหาคล้ายกันอยู่  ซึ่งจะมีวิธีการดังนี้ค่ะ

    1.ดึงข้อมูลไฟล์แนบเอกสารทั้งหมดของผู้ใช้

      DataTable dtFile = new DataTable();
    
        //เป็นส่วนของการสมมุติการดึงข้อมูลการแนบไฟล์ของผู้ใช้ออกมาในรูปแบบ Datatable
            dtFile.Columns.AddRange(new DataColumn[2] { 
                             new DataColumn("CITIZEN_ID", typeof(string)),
                            new DataColumn("FILE_PATH",typeof(string))});
            dtFile.Rows.Add("xxxxxxxxxxxx", "resumeFiles/Document1.pdf");
            dtFile.Rows.Add("xxxxxxxxxxxx", "resumeFiles/Document2.pdf");
            dtFile.Rows.Add("xxxxxxxxxxxx", "resumeFiles/Document3.pdf");
            dtFile.Rows.Add("xxxxxxxxxxxx", "resumeFiles/Image.png");
             
    
    //สร้างตัวแปรในการเก็บค่าชื่อไฟล์ เพื่อใช้ในการส่งเป็นพารามิเตอร์ในการรวมไฟล์
            List<string> listFiles = new List<string>();
            string path = Server.MapPath("../registPDF");
    
    //ตั้งชื่อไฟล์ที่จะรวมไฟล์ทั้งหมดไว้ และประกาศตัวแปรต่างๆที่จำเป็นต้องใช้ในการสร้างและรวมไฟล์
            string genName = Guid.NewGuid().ToString() + ".pdf";
    
    //ตัวแปร tmpPath เป็นตัวแปรที่เป็นชื่อไฟล์ที่สร้างขึ้นเพื่อรวมไฟล์ทั้งหมด
    
            string tmpPath = "../registPDF/" + genName;
            string[] files = Directory.GetFiles(path);
            string[] fileName;
            string DestName = "";
    
    //กำหนดนามสกุลที่ต้องการตรวจสอบว่าเป็นไฟล์รูปภาพหรือไม่
            string[] ImgExt = { "png","jpg","jpeg","gif"};
    
           /// เป็นการลบ Temporary file ที่ถูกสร้างขุึ้นเพื่อรวมไฟล์ เพื่อไม่ให้มีไฟล์ที่ไม่ใช้งานค้างอยู่ในเซิร์ฟเวอร์มากเกินไป *****
            foreach (string file in files)
            {
                FileInfo fi = new FileInfo(file);
                if (fi.LastAccessTime < DateTime.Now.AddMinutes(-30))
                    fi.Delete();
            }
          
    
          //วนค่าเพื่อเก็บตัวแปรชื่อไฟล์แนบก่อนรวมไฟล์
    
            for (int i = 0; i <= dtFile.Rows.Count - 1; i++)
            {
    
         //ตรวจสอบว่ามีไฟล์ดังกล่าวอยู่จริงหรือไม่บนเซิร์ฟเวอร์ตามที่อยู่ไฟล์ที่อ้างถึง
                if (File.Exists(Server.MapPath("../" + dtFile.Rows[i]["FILE_PATH"].ToString())))
                {
    
         //ตรวจสอบชนิดของไฟล์ว่ามีนามสกุลอะไร หากไม่ใช่ไฟล์ PDF จะต้องทำการแปลงและสร้างเป็นไฟล์ PDF ก่อนส่งไปรวมไฟล์
                    fileName = dtFile.Rows[i]["FILE_PATH"].ToString().Split('.');
                    if (fileName[1] == "pdf")
                        listFiles.Add(Server.MapPath("../" + dtFile.Rows[i]["FILE_PATH"].ToString()));
                    else 
                    {
    
         //กรณีที่พบว่าไม่ใช่ไฟล์ PDF จะตรวจสอบว่าเป็นไฟล์รูปภาพหรือไม่ หากใช่จะทำการแปลงและสร้างเป็นไฟล์ PDF ก่อนส่งไปรวมไฟล์
                        if (ImgExt.Contains(fileName[1].ToLower()))
                        {
                            DestName = "../registPDF/"  + Guid.NewGuid().ToString() + ".pdf";
                            ConvertImageToPdf(Server.MapPath("../" + dtFile.Rows[i]["FILE_PATH"].ToString()), Server.MapPath(DestName));
                            listFiles.Add(Server.MapPath( DestName));
                        }
                    }
                } 
     
            }
    
    //เรียกใช้งานเมธอดในการรวมไฟล์ โดยส่งค่าลิสต์ของชื่อไฟล์ PDF ทั้งหมดที่ต้องการรวม และชื่อไฟล์ปลายทางที่จะใช้ในการรวม
    
            CombineMultiplePDFs(listFiles.ToArray(), Server.MapPath(tmpPath));
    
    
    //แสดงผล PDF ไฟล์ที่ได้ทำการรวมเรียบร้อยแล้วด้วย Literal โดยตัวแปร tmpPath คือที่อยู่ของไฟล์ใหม่ที่ทำการรวมไฟล์ PDF ทั้งหมดเรียบร้อยแล้ว
    
    
            StringBuilder strObj = new StringBuilder();
    
            strObj.Append("<object id=\"pdfContainer\" type=\"application/pdf\"");
            strObj.AppendFormat(" data=\"{0}#toolbar=1&amp;navpanes=0&amp;scrollbar=1\" style=\" z-index:1000; width: 99%;  height: 600px;\">", tmpPath);
            strObj.AppendFormat(" <param name=\"src\" value=\"{0}#toolbar=1&amp;navpanes=0&amp;scrollbar=1\"> ", tmpPath);
            strObj.Append(" </object>");
    
            ltrPDF.Text = strObj.ToString();
            dtFile = null;
            

    หมายเหตุ ในการทำงานข้างต้น ควรมีการลบไฟล์(Temporary file)ที่ถูกสร้างไว้ก่อนหน้านี้ที่ไม่ใช้งานออกไปด้วย เนื่องจากการรวมไฟล์ด้วยวิธีนี้จะมีการสร้างไฟล์รวมตัวใหม่ขึ้นมาและนำไปแสดงผลให้ผู้ใช้ ซึ่งหลังจากผู้ใช้งานไม่ใช้งานแล้วหากเราไม่ทำการลบทิ้งจะเกิดเป็นไฟล์ขยะบนเซิร์ฟเวอร์จำนวนมากได้

              โดยจากโค้ดข้างต้นจะพบว่า ไฟล์ที่จะใช้ในการรวบรวมจะต้องเป็นไฟล์ PDF ซึ่งในการทำงานจริงของเรา การแนบไฟล์เอกสาร/หลักฐานสามารถแนบได้ทั้งไฟล์ที่เป็น PDF และไฟล์ที่เป็นรูปภาพด้วย ดังนั้น ก่อนที่จะทำการรวมไฟล์ จึงต้องทำการตรวจสอบว่ามีไฟล์ดังกล่าวอยู่จริงหรือไม่ รวมทั้งตรวจสอบชนิดของไฟล์ด้วย หากพบว่าไฟล์ดังกล่าวไม่ได้อยู่ในรูปแบบ PDF ไฟล์ ให้ทำการแปลงไฟล์รูปภาพเหล่านั้นให้เป็น PDF เสียก่อน เพื่อป้องกันความผิดพลาดที่จะเกิดขึ้นในขณะทำการรวมไฟล์นั่นเอง

    2. เขียนเมธอดในการรวมไฟล์ดังกล่าวและสร้างเป็นไฟล์ PDF ตัวใหม่

        public static void CombineMultiplePDFs(string[] fileNames, string outFile)
        {
            // ขั้นที่ 1: สร้าง document ที่จะรวมไฟล์ทั้งหมดขึ้นมา
            Document document = new Document();
            // สร้าง FileStream object ที่จะใช้งานและต้องอย่าลืม dispose เมื่อใช้งานเรียบร้อยแล้ว
            using (FileStream newFileStream = new FileStream(outFile, FileMode.Create))
            {
                // ขั้นที่ 2: สร้างตัว
                PdfCopy writer = new PdfCopy(document, newFileStream);
                if (writer == null)
                {
                    return;
                }
    
                //ขั้นที่ 3:เปิดการใช้งานตัว document
                document.Open();
    
              // วนเพื่ออ่านค่าชื่อไฟล์ และทำการเพิ่มข้อมูลลงในเอกสารตัวใหม่ที่จะรวมไฟล์ทั้งหมด
    
               foreach (string fileName in fileNames)
                {
                    // สร้างตัว reader จากเอกสารแนบที่กำลังวน
                    PdfReader reader = new PdfReader(fileName);
                    reader.ConsolidateNamedDestinations();
    
                    // ขั้นที่ 4: ทำการเพิ่มหน้าข้อมูลจาก reader ให้กับตัว writer ทีละหน้า
                    for (int i = 1; i <= reader.NumberOfPages; i++)
                    {
                        PdfImportedPage page = writer.GetImportedPage(reader, i);
                        writer.AddPage(page);
                    }
    
                    PRAcroForm form = reader.AcroForm;
                    if (form != null)
                    {
                        writer.CopyAcroForm(reader);
                    }
    
                    reader.Close();
                }
    
                // ขั้นที่ 5: ปิดการทำงาน document และ writer
                writer.Close();
                document.Close();
            } 
        }
    

    3.เขียนเมธอดในแปลงไฟล์รูปภาพให้เป็นไฟล์ PDF

     public static void ConvertImageToPdf(string srcFilename, string dstFilename)
        {
            iTextSharp.text.Rectangle pageSize = null;
    
            using (var srcImage = new Bitmap(srcFilename))
            {
                pageSize = new iTextSharp.text.Rectangle(0, 0, srcImage.Width, srcImage.Height);
            }
            using (var ms = new MemoryStream())
            {
                var document = new iTextSharp.text.Document(pageSize, 0, 0, 0, 0);
                iTextSharp.text.pdf.PdfWriter.GetInstance(document, ms).SetFullCompression();
                document.Open();
                var image = iTextSharp.text.Image.GetInstance(srcFilename);
                document.Add(image);
                document.Close();
    
                File.WriteAllBytes(dstFilename, ms.ToArray());
            }
        }

    4.แสดงผลไฟล์ PDF ที่รวมเรียบร้อยแล้ว ด้วย Literal

            StringBuilder strObj = new StringBuilder();
    
            strObj.Append("<object id=\"pdfContainer\" type=\"application/pdf\"");
            strObj.AppendFormat(" data=\"{0}#toolbar=1&amp;navpanes=0&amp;scrollbar=1\" style=\" z-index:1000; width: 99%;  height: 600px;\">", tmpPath);
            strObj.AppendFormat(" <param name=\"src\" value=\"{0}#toolbar=1&amp;navpanes=0&amp;scrollbar=1\"> ", tmpPath);
            strObj.Append(" </object>");
    
            ltrPDF.Text = strObj.ToString();
    

    หมายเหตุ ในการใช้งานโค้ดข้างต้น มีไลบรารีที่จำเป็นต้องใช้งาน ดังนี้ค่ะ

    using System.IO;
    using iTextSharp.text;
    using iTextSharp.text.pdf;
    using System.Data;
    using System.Text;
    using System.Drawing;

    ผลลัพธ์ ตัวอย่างไฟล์ที่ได้จากการรวมไฟล์เอกสาร PDF 3 ไฟล์ และไฟล์รูปภาพ 1 ไฟล์

              ซึ่งวิธีการนี้เป็นเพียงหนึ่งในแนวทางแก้ปัญหาในการแสดงผลไฟล์ PDF หลายๆไฟล์ในครั้งเดียวเท่านั้น และอาจมีข้อจำกัดหากผู้ใช้มีการแนบไฟล์จำนวนมาก เนื่องจากจะส่งผลให้ขนาดของไฟล์ที่รวมได้มีขนาดใหญ่มากตามไปด้วย ในส่วนของการแนบไฟล์จึงควรมีการจำกัดขนาดและรูปแบบให้เหมาะสมในการแนบไฟล์แต่ละครั้ง เพื่อประหยัดเนื้อที่ในการจัดเก็บไฟล์บนเซิร์ฟเวอร์ด้วย และผู้เขียนหวังเป็นอย่างยิ่งว่าบทความนี้จะช่วยแก้ปัญหาให้กับนักพัฒนาที่กำลังประสบปัญหาเดียวกันอยู่ไม่มากก็น้อยนะคะ ขอบคุณค่ะ ^^

    แหล่งอ้างอิง

    https://stackoverflow.com/questions/6029142/merging-multiple-pdfs-using-itextsharp-in-c-net

    https://alandjackson.wordpress.com/2013/09/27/convert-an-image-to-a-pdf-in-c-using-itextsharp/