asp.net MVC设计模式中使用iTextSharp实现html字符串生成PDF文件

  因个人需求,需要将html格式转换成PDF并加上水印图片。于是乎第一次接触这种需求的小菜鸟博主我,在某度搜索引擎上不断的查阅关键字资料、踩坑,终于有了一个相应的解决方案。以下是解决步骤,记录下来方便以后的回顾,以及各位大神们的品鉴。

  1、在 NuGet 搜索 itextsharp 关键字 下载以下截图圈中的两个包,一般下载完后项目会自引用。

asp.net MVC设计模式中使用iTextSharp实现html字符串生成PDF文件_第1张图片asp.net MVC设计模式中使用iTextSharp实现html字符串生成PDF文件_第2张图片

 

  2、在项目文件中引入以下命名空间(建议下面提及的代码封装成类库,方便项目间调用,个人取舍)

 

  3、Html字符串转pdf文件流,加水印图片以及未加水印重载 精简帮助类(由博主踩坑整理,仅完成个人业务需求)

 1     /// 
 2     /// Html字符串转PDF输出帮助类
 3     /// 
 4     public class HtmlToPdfHelper
 5     {
 6         #region HtmlToPDF
 7 
 8         /// 
 9         /// 判断是否有乱码
10         /// 
11         /// 
12         /// 
13         private static bool IsMessyCode(string txt)
14         {
15             var bytes = Encoding.UTF8.GetBytes(txt);
16             for (var i = 0; i < bytes.Length; i++)
17             {
18                 if (i < bytes.Length - 3)
19                     if (bytes[i] == 239 && bytes[i + 1] == 191 && bytes[i + 2] == 189)
20                     {
21                         return true;
22                     }
23             }
24             return false;
25         }
26 
27         /// 
28         /// 将Html字符串 输出到PDF档里
29         /// 
30         /// 
31         /// 
32         public static byte[] ConvertHtmlTextToPdf(string htmlText)
33         {
34             return ConvertHtmlTextToPdf(htmlText, "", 0, 0, 0, 0);
35         }
36 
37         /// 
38         /// 将Html字符串 输出到PDF档里,并添加水印
39         /// 
40         /// 网页代码
41         /// 水印路径
42         /// 距离左边距离
43         /// 距顶部距离
44         /// 水印宽度
45         /// 水印高度
46         /// 
47         public static byte[] ConvertHtmlTextToPdf(string htmlText, string picPath, int left, int top, int width, int height)
48         {
49             if (string.IsNullOrEmpty(htmlText))
50             {
51                 return null;
52             }
53             //避免当htmlText无任何html tag标签的纯文字时,转PDF时会挂掉,所以一律加上

标签 54 htmlText = "

" + htmlText + "

"; 55 MemoryStream outputStream = new MemoryStream();//要把PDF写到哪个串流 56 byte[] data = Encoding.UTF8.GetBytes(htmlText);//字串转成byte[] 57 MemoryStream msInput = new MemoryStream(data); 58 Document doc = new Document();//要写PDF的文件,建构子没填的话预设直式A4 59 PdfWriter writer = PdfWriter.GetInstance(doc, outputStream); 60 //指定文件预设开档时的缩放为100% 61 PdfDestination pdfDest = new PdfDestination(PdfDestination.XYZ, 0, doc.PageSize.Height, 1f); 62 //开启Document文件 63 doc.Open(); 64 65 //写入水印图片 66 if (!string.IsNullOrEmpty(picPath)) 67 { 68 Image img = Image.GetInstance(picPath); 69 //设置图片的位置 70 img.SetAbsolutePosition(width + left, (doc.PageSize.Height - height) - top); 71 //设置图片的大小 72 img.ScaleAbsolute(width, height); 73 doc.Add(img); 74 } 75 try 76 { 77 //使用XMLWorkerHelper把Html parse到PDF档里 79 XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msInput, null, Encoding.UTF8); 80 //将pdfDest设定的资料写到PDF档 81 PdfAction action = PdfAction.GotoLocalPage(1, pdfDest, writer); 82 writer.SetOpenAction(action); 83 } 84 catch (Exception) 85 { 86 return null; 87 } 88 doc.Close(); 89 msInput.Close(); 90 outputStream.Close(); 91 //回传PDF档案 92 return outputStream.ToArray(); 94 } 95 96 #endregion 97 98 }

 

  4、获取网页字符串方法

 1         /// 
 2         /// 获取网站内容,包含了 HTML+CSS+JS
 3         /// 
 4         /// String返回网页信息
 5         public static string GetWebContent(string inpath)
 6         {
 7             try
 8             {
 9                 WebClient myWebClient = new WebClient();
10                 //获取或设置用于向Internet资源的请求进行身份验证的网络凭据
11                 myWebClient.Credentials = CredentialCache.DefaultCredentials;
12                 //从指定网站下载数据
13                 Byte[] pageData = myWebClient.DownloadData(inpath);
14                 //如果获取网站页面采用的是GB2312,则使用这句
15                 string pageHtml = Encoding.UTF8.GetString(pageData);
16                 bool isBool = IsMessyCode(pageHtml);//判断使用哪种编码 读取网页信息
17                 if (!isBool)
18                 {
19                     string pageHtml1 = Encoding.UTF8.GetString(pageData);
20                     pageHtml = pageHtml1;
21                 }
22                 else
23                 {
24                     string pageHtml2 = Encoding.Default.GetString(pageData);
25                     pageHtml = pageHtml2;
26                 }
27                 return pageHtml;
28             }
29             catch (WebException webEx)
30             {
31                 return webEx.Message;
32             }
33         }

 

  5、MVC设计模式下获取控制器视图Html方法,很XX的一个问题就是只能获取调用此方法的控制器下所有视图,不能跨控制器获取视图,有待优化

 1         /// 
 2         /// 获取MVC视图Html
 3         /// 
 4         /// 控制器上下文
 5         /// 视图名称
 6         /// 
 7         /// 
 8         public static string GetViewHtml(ControllerContext context, string viewName)
 9         {
10             if (string.IsNullOrEmpty(viewName))
11                 viewName = context.RouteData.GetRequiredString("action");
12             using (var sw = new StringWriter())
13             {
14                 ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(context, viewName);
15                 var viewContext = new ViewContext(context, viewResult.View, context.Controller.ViewData, context.Controller.TempData, sw);
16                 try
17                 {
18                     viewResult.View.Render(viewContext, sw);
19                 }
20                 catch (Exception ex)
21                 {
22                     throw;
23                 }
24 
25                 return sw.GetStringBuilder().ToString();
26             }
27         }

 

  6、将pdf流输出至客户浏览器下载方法

 1         /// 
 2         /// 将pdf文件流输出至浏览器下载
 3         /// 
 4         /// PDF文件流
 5         public static void PdfDownload(byte[] pdfFile)
 6         {
 7             byte[] buffer = pdfFile;
 8             Stream iStream = new MemoryStream(buffer);
 9             try
10             {
11                 int length;
12                 long dataToRead;
13                 string filename = DateTime.Now.ToString("yyyyMMddHHmmss") + ".pdf";//保存的文件名称
14                 dataToRead = iStream.Length;
15                 HttpContext.Current.Response.Clear();
16                 HttpContext.Current.Response.ClearHeaders();
17                 HttpContext.Current.Response.ClearContent();
18                 HttpContext.Current.Response.ContentType = "application/pdf"; //文件类型 
19                 HttpContext.Current.Response.AddHeader("Content-Length", dataToRead.ToString());//添加文件长度,进而显示进度 
20                 HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(filename, Encoding.UTF8));
21                 while (dataToRead > 0)
22                 {
23                     if (HttpContext.Current.Response.IsClientConnected)
24                     {
25                         length = buffer.Length;
26                         HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
27                         HttpContext.Current.Response.Flush();
28                         buffer = new Byte[length];
29                         dataToRead = dataToRead - length;
30                     }
31                     else
32                     {
33                         dataToRead = -1;
34                     }
35                 }
36             }
37             catch (Exception ex)
38             {
39                 HttpContext.Current.Response.Write("文件下载时出现错误!");
40             }
41             finally
42             {
43                 if (iStream != null)
44                 {
45                     iStream.Close();
46                 }
47                 //结束响应,否则将导致网页内容被输出到文件,进而文件无法打开  
48                 HttpContext.Current.Response.Flush();
49                 HttpContext.Current.Response.End();
50 
51             }
52         }

 

  7、MVC控制器下调用Demo(步骤4、6 方法封装至帮助类)

 1     public class HomeController : Controller
 2     {
 3         //
 4         // GET: /Home/
 5 
 6         public ActionResult Index()
 7         {
 8             //从网址下载Html字符串(方法一)
 9             string inpath = System.Web.HttpContext.Current.Server.MapPath("~/PDFTemplate/test.html");
10             string htmlText = HtmlToPdfHelper.GetWebContent(inpath);//此处调用步骤4方法
11 
12             //获取MVC视图Html字符串(方法二)
13             //string htmlText = GetViewHtml(ControllerContext, "Test");//此处调用步骤5方法
14 
15             //水印图片路径
16             string picPath = Server.MapPath("~/PDFTemplate/TemplateImg/authentication-iocn.png");
17             //html转pdf并加上水印
18             byte[] pdfFile = HtmlToPdfHelper.ConvertHtmlTextToPdf(htmlText, picPath, 100, 200, 100, 100);
19             //输出至客户端
20             HtmlToPdfHelper.PdfDownload(pdfFile);//此处调用步骤6方法
21 
22             return View();
23         }
24 
25         public ActionResult Test()
26         {
27             return View();
28         }
29 
30         /// 
31         /// 获取MVC视图Html
32         /// 
33         /// 
34         /// 视图名称
35         /// 
36         public static string GetViewHtml(ControllerContext context, string viewName)
37         {
38             if (string.IsNullOrEmpty(viewName))
39                 viewName = context.RouteData.GetRequiredString("action");
40             using (var sw = new StringWriter())
41             {
42                 ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(context, viewName);
43                 var viewContext = new ViewContext(context, viewResult.View, context.Controller.ViewData,
44                     context.Controller.TempData, sw);
45                 try
46                 {
47                     viewResult.View.Render(viewContext, sw);
48                 }
49                 catch (Exception ex)
50                 {
51                     throw;
52                 }
53 
54                 return sw.GetStringBuilder().ToString();
55             }
56         }
57     }

 

  总结:我理解的解决思路是将html读取转换成字符串,之后再通过 itextsharp 转换成 pdf 比特流 传输至客户端或直接保存至服务器生成链接供用户下载。(新手上路,不妥之处,欢迎各位大神指教)

  以上代码仅满足个人业务逻辑需求,如侵删,谢谢浏览。

 

你可能感兴趣的:(asp.net MVC设计模式中使用iTextSharp实现html字符串生成PDF文件)