ASP. NET MVC項目 使用iTextSharp將網頁代碼生成PDF文件


一、功能背景:

  1.一直在完善公司內部的數據驅動平台系統,最近給我一個值班表的功能,大體功能需求如圖(展示每月值班表,需要實現編輯、打印、模板及生成PDF)

二、功能介紹

  1.前三個編輯、打印、模板功能使用UEditor編輯器都能輕松實現

    ueditor模板修改:①.找到目錄下 ueditor/dialogs/template/config.js 文件,將原模板的標題及內容替換成自己的就OK

            ②.若替換后不顯示,清一下瀏覽器緩存就OK了

  2.比較頭疼的便是將tab標簽下的網頁上展示的內容生成PDF模板的功能,自己查了一下午還是覺得iTextSharp比較容易操作。

    第一步:我們先將iTextSharp所需要引用的NuGet程序包添加安裝到項目中(添加引用——管理NuGet程序包——聯機搜索iTextSharp——安裝)

    第二步:創建PDFHelper幫助類(標紅的為使用iTextSharp需要引用的)

  1 using System;
  2 using System.Collections.Generic;
  3 using System.IO;
  4 using System.Linq;
  5 using System.Net;
  6 using System.Text;
  7 using System.Threading.Tasks;
  8 using System.Web;
  9 using iTextSharp.text;
 10 using iTextSharp.text.pdf;
 11 using iTextSharp.tool.xml;
 12 
 13 namespace Labthink.BI.Helpers
 14 {
 15     /// <summary>
 16     /// Html字符串轉PDF輸出幫助類
 17     /// </summary>
 18     public class HtmlToPdfHelper
 19     {
 20         #region HtmlToPDF
 21 
 22         /// <summary>
 23         /// 判斷是否有亂碼
 24         /// </summary>
 25         /// <param name="txt"></param>
 26         /// <returns></returns>
 27         private static bool IsMessyCode(string txt)
 28         {
 29             var bytes = Encoding.UTF8.GetBytes(txt);
 30             for (var i = 0; i < bytes.Length; i++)
 31             {
 32                 if (i < bytes.Length - 3)
 33                     if (bytes[i] == 239 && bytes[i + 1] == 191 && bytes[i + 2] == 189)
 34                     {
 35                         return true;
 36                     }
 37             }
 38             return false;
 39         }
 40 
 41         /// <summary>
 42         /// 將Html字符串 輸出到PDF檔里
 43         /// </summary>
 44         /// <param name="htmlText"></param>
 45         /// <returns></returns>
 46         public static byte[] ConvertHtmlTextToPdf(string htmlText)
 47         {
 48             return ConvertHtmlTextToPdf(htmlText, "", 0, 0, 0, 0);
 49         }
 50 
 51         /// <summary>
 52         /// 將Html字符串 輸出到PDF檔里,並添加水印
 53         /// </summary>
 54         /// <param name="htmlText">網頁代碼</param>
 55         /// <param name="picPath">水印路徑</param>
 56         /// <param name="left">距離左邊距離</param>
 57         /// <param name="top">距頂部距離</param>
 58         /// <param name="width">水印寬度</param>
 59         /// <param name="height">水印高度</param>
 60         /// <returns></returns>
 61         public static byte[] ConvertHtmlTextToPdf(string htmlText, string picPath, int left, int top, int width, int height)
 62         {
 63             if (string.IsNullOrEmpty(htmlText))
 64             {
 65                 return null;
 66             }
 67             //避免當htmlText無任何html tag標簽的純文字時,轉PDF時會掛掉,所以一律加上<p>標簽
 68             htmlText = "<p>" + htmlText + "</p>";
 69             MemoryStream outputStream = new MemoryStream();//要把PDF寫到哪個串流
 70             byte[] data = Encoding.UTF8.GetBytes(htmlText);//字串轉成byte[]
 71             MemoryStream msInput = new MemoryStream(data);
 72             //Rectangle rect = new Rectangle(11 * 72, 8.5f * 72);自定義紙張大小
 73             Document doc = new Document(PageSize._11X17, 20, 0, 20, 0);//要寫PDF的文件,建構子沒填的話預設直式A4
 74             PdfWriter writer = PdfWriter.GetInstance(doc, outputStream);
 75             //指定文件預設開檔時的縮放為100%
 76             PdfDestination pdfDest = new PdfDestination(PdfDestination.XYZ, 0, doc.PageSize.Height, 1f);
 77             //開啟Document文件 
 78             doc.Open();
 79 
 80             //寫入水印圖片
 81             if (!string.IsNullOrEmpty(picPath))
 82             {
 83                 Image img = Image.GetInstance(picPath);
 84                 //設置圖片的位置
 85                 img.SetAbsolutePosition(width + left, (doc.PageSize.Height - height) - top);
 86                 //設置圖片的大小
 87                 img.ScaleAbsolute(width, height);
 88                 doc.Add(img);
 89             }
 90             try
 91             {
 92                 //使用XMLWorkerHelper把Html parse到PDF檔里
 93                 XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msInput, null, Encoding.UTF8);
 94                 //將pdfDest設定的資料寫到PDF檔
 95                 PdfAction action = PdfAction.GotoLocalPage(1, pdfDest, writer);
 96                 writer.SetOpenAction(action);
 97             }
 98             catch (Exception)
 99             {
100                 return null;
101             }
102             doc.Close();
103             msInput.Close();
104             outputStream.Close();
105             //回傳PDF檔案 
106             return outputStream.ToArray();
107         }
108 
109         #endregion
110         該注釋掉的方法為獲取某文件下的HTML代碼來生成PDF,因為我是直接取的數據庫中存的HTML代碼,所以改成了下面的方法。
111         /// <summary>
112         /// 獲取網站內容,包含了 HTML+CSS+JS
113         /// </summary>
114         /// <returns>String返回網頁信息</returns>
115         //public static string GetWebContent(string inpath)
116         //{
117         //    try
118         //    {
119         //        WebClient myWebClient = new WebClient();
120         //        //獲取或設置用於向Internet資源的請求進行身份驗證的網絡憑據
121         //        myWebClient.Credentials = CredentialCache.DefaultCredentials;
122         //        //從指定網站下載數據
123         //        Byte[] pageData = myWebClient.DownloadData(inpath);
124         //        //如果獲取網站頁面采用的是GB2312,則使用這句
125         //        string pageHtml = Encoding.UTF8.GetString(pageData);
126         //        bool isBool = IsMessyCode(pageHtml);//判斷使用哪種編碼 讀取網頁信息
127         //        if (!isBool)
128         //        {
129         //            string pageHtml1 = Encoding.UTF8.GetString(pageData);
130         //            pageHtml = pageHtml1;
131         //        }
132         //        else
133         //        {
134         //            string pageHtml2 = Encoding.Default.GetString(pageData);
135         //            pageHtml = pageHtml2;
136         //        }
137         //        return pageHtml;
138         //    }
139         //    catch (WebException webEx)
140         //    {
141         //        return webEx.Message;
142         //    }
143         //}
144         public static string GetWebContent(string monthContent)
145         {
146             try
147             {
148                 WebClient myWebClient = new WebClient();
149                 //獲取或設置用於向Internet資源的請求進行身份驗證的網絡憑據
150                 myWebClient.Credentials = CredentialCache.DefaultCredentials;
151                 //從指定網站下載數據
152                 //Byte[] pageData = myWebClient.DownloadData(inpath);
153                 //如果獲取網站頁面采用的是GB2312,則使用這句
154                 string pageHtml = monthContent;
155                 //bool isBool = IsMessyCode(pageHtml);//判斷使用哪種編碼 讀取網頁信息
156                 //if (!isBool)
157                 //{
158                 //    string pageHtml1 = Encoding.UTF8.GetString(pageData);
159                 //    pageHtml = pageHtml1;
160                 //}
161                 //else
162                 //{
163                 //    string pageHtml2 = Encoding.Default.GetString(pageData);
164                 //    pageHtml = pageHtml2;
165                 //}
166                 return pageHtml;
167             }
168             catch (WebException webEx)
169             {
170                 return webEx.Message;
171             }
172         }
173 
174         /// <summary>
175         /// 將pdf文件流輸出至瀏覽器下載
176         /// </summary>
177         /// <param name="pdfFile">PDF文件流</param>
178         public static void PdfDownload(byte[] pdfFile,string title)
179         {
180             byte[] buffer = pdfFile;
181             Stream iStream = new MemoryStream(buffer);
182             try
183             {
184                 int length;
185                 long dataToRead;
186                 //string filename = DateTime.Now.ToString("yyyyMMddHHmmss") + ".pdf";//保存的文件名稱
187                 string filename = title + ".pdf";
188                 dataToRead = iStream.Length;
189                 HttpContext.Current.Response.Clear();
190                 HttpContext.Current.Response.ClearHeaders();
191                 HttpContext.Current.Response.ClearContent();
192                 HttpContext.Current.Response.ContentType = "application/pdf"; //文件類型 
193                 HttpContext.Current.Response.AddHeader("Content-Length", dataToRead.ToString());//添加文件長度,進而顯示進度 
194                 HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(filename, Encoding.UTF8));
195                 while (dataToRead > 0)
196                 {
197                     if (HttpContext.Current.Response.IsClientConnected)
198                     {
199                         length = buffer.Length;
200                         HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
201                         HttpContext.Current.Response.Flush();
202                         buffer = new Byte[length];
203                         dataToRead = dataToRead - length;
204                     }
205                     else
206                     {
207                         dataToRead = -1;
208                     }
209                 }
210             }
211             catch (Exception ex)
212             {
213                 HttpContext.Current.Response.Write("文件下載時出現錯誤!");
214             }
215             finally
216             {
217                 if (iStream != null)
218                 {
219                     iStream.Close();
220                 }
221                 //結束響應,否則將導致網頁內容被輸出到文件,進而文件無法打開  
222                 HttpContext.Current.Response.Flush();
223                 HttpContext.Current.Response.End();
224             }
225         }
226     }
227 }

    第三步:控制器中需要添加的代碼

        /// <summary>
        /// 獲取MVC視圖Html
        /// </summary>
        /// <param name="context">控制器上下文</param>
        /// <param name="viewName">視圖名稱</param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static string GetViewHtml(ControllerContext context, string viewName)
        {
            if (string.IsNullOrEmpty(viewName))
                viewName = context.RouteData.GetRequiredString("action");
            using (var sw = new StringWriter())
            {
                ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(context, viewName);
                var viewContext = new ViewContext(context, viewResult.View, context.Controller.ViewData, context.Controller.TempData, sw);
                try
                {
                    viewResult.View.Render(viewContext, sw);
                }
                catch (Exception ex)
                {
                    throw;
                }

                return sw.GetStringBuilder().ToString();
            }
        }

        [NoAuthorization]
        public ActionResult IndexPdf(string Year, string month)
        {
            //獲取值班內容
            string monthContent = helper.GetRotaMonth(Year, month);
            //值班標題
            string title = "";
            //從網址下載Html字符串(方法一)
            //string inpath = System.Web.HttpContext.Current.Server.MapPath("~/Upload/Rota/September.html");
       //string htmlText = HtmlToPdfHelper.GetWebContent(inpath)//如果讀取文件中的HTML代碼調用此方法
            string htmlText = HtmlToPdfHelper.GetWebContent(monthContent);//這是調用的我獲取的數據庫中的內容
            //獲取MVC視圖Html字符串(方法二)
            //string htmlText = GetViewHtml(ControllerContext, "EditIndex");
//如果直接調用視圖中的HTML調調用此方法,不建議用此方法,因為視圖中有數據會是動態生成的,這時會獲取不到報錯 //水印圖片路徑 //string picPath = Server.MapPath("~/PDFTemplate/TemplateImg/authentication-iocn.png"); //string picPath = Server.MapPath("~/Upload/Rota/authentication-iocn.png"); //html轉pdf並加上水印 //byte[] pdfFile = HtmlToPdfHelper.ConvertHtmlTextToPdf(htmlText, "", 100, 200, 100, 100); byte[] pdfFile = HtmlToPdfHelper.ConvertHtmlTextToPdf(htmlText); //輸出至客戶端 HtmlToPdfHelper.PdfDownload(pdfFile, title);//此處調用步驟6方法 return View(); }

  這就是使用iTextSharp生成PDF的方法,但是生成的PDF格式和正常做的會稍有不同。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM