zoukankan      html  css  js  c++  java
  • ASP.NET MVC 拓展ActionResult实现Html To Pdf 导出

    之前实现了html直接转换为word文档的功能,那么是否也同样可以直接转换为pdf文档呢,网上搜了下html to pdf 的开源插件有很多 如:wkhtmltopdf,pdfsharp,itextsharp等

    本文使用itextsharp实现如何将html文件转换为pdf文档

     

    首先使用Nuget安装itextsharp插件

    1. Install-Package itextsharp.xmlworker

    创建FileContentResult文件继承自ActionResult,方法HtmlToPdf中实现了如何将一段html转换为pdf文档逻辑,itextsharp.xmlworker能够支持丰富的css和html标签,但是有一个很大的缺点就是不支持中文,网上的一些解决中文字体的逻辑,在新版里面已经不支持了,在以下的示例代码中已经解决此问题,重点是以下两部代码:

    FontFactory.RegisterDirectories();//注册当前系统中所支持的字体

    worker.ParseXHtml(pdfWriter, document, new MemoryStream(Encoding.UTF8.GetBytes(sbHtml.ToString())), null, Encoding.UTF8, new UnicodeFontFactory()); //指定要使用的字体

     

    1. public class PdfContentResult : ActionResult
    2. {
    3.     public PdfContentResult() : this(null, null) { }
    4.  
    5.     public PdfContentResult(string viewName) : this(null, viewName) { }
    6.  
    7.     public PdfContentResult(object model) : this(model, null) { }
    8.  
    9.     public PdfContentResult(object model, string viewName)
    10.     {
    11.         this.ViewName = viewName;
    12.         ViewData = null != model ? new ViewDataDictionary(model) : null;
    13.     }
    14.  
    15.     public ViewDataDictionary ViewData { get; set; } = new ViewDataDictionary();
    16.  
    17.     public string ViewName { get; set; }
    18.  
    19.     public IView View { get; set; }
    20.  
    21.     public override void ExecuteResult(ControllerContext context)
    22.     {
    23.         if (String.IsNullOrEmpty(ViewName))
    24.         {
    25.             ViewName = context.RouteData.GetRequiredString("action");
    26.         }
    27.         if (ViewData == null)
    28.         {
    29.             ViewData = context.Controller.ViewData;
    30.         }
    31.         ViewEngineResult result = ViewEngines.Engines.FindView(context, ViewName, null);
    32.         View = result.View;
    33.  
    34.         StringBuilder sbHtml = new StringBuilder();
    35.         TextWriter txtWriter = new StringWriter(sbHtml);
    36.         ViewContext viewContext = new ViewContext(context, View, ViewData, context.Controller.TempData, txtWriter);
    37.         result.View.Render(viewContext, txtWriter);
    38.  
    39.         HttpResponseBase httpResponse = context.HttpContext.Response;
    40.         httpResponse.ContentType = System.Net.Mime.MediaTypeNames.Application.Pdf;
    41.  
    42.         //加入此头部文件会直接下载pdf文件,而不是在浏览器中预览呈现
    43.         //context.HttpContext.Response.AppendHeader("Content-Disposition", string.Format("attachment;filename={0}.pdf", ViewName));
    44.  
    45.         HtmlToPdf(sbHtml, httpResponse);
    46.  
    47.         result.ViewEngine.ReleaseView(context, View);
    48.     }
    49.  
    50.     private static void HtmlToPdf(StringBuilder sbHtml, HttpResponseBase httpResponse)
    51.     {
    52.         using (Document document = new Document(PageSize.A4, 4, 4, 4, 4))
    53.         {
    54.             using (PdfWriter pdfWriter = PdfWriter.GetInstance(document, httpResponse.OutputStream))
    55.             {
    56.                 document.Open();
    57.                 FontFactory.RegisterDirectories();//注册系统中所支持的字体
    58.                 XMLWorkerHelper worker = XMLWorkerHelper.GetInstance();
    59.                 //UnicodeFontFactory 自定义实现解决itextsharp.xmlworker 不支持中文的问题
    60.                 worker.ParseXHtml(pdfWriter, document, new MemoryStream(Encoding.UTF8.GetBytes(sbHtml.ToString())), null, Encoding.UTF8, new UnicodeFontFactory());
    61.                 document.Close();
    62.             }
    63.         }
    64.     }
    65. }

     

    UnicodeFontFactory完整代码

     

    1. public class UnicodeFontFactory : FontFactoryImp
    2. {
    3.     static UnicodeFontFactory()
    4.     {
    5.  
    6.     }
    7.     public override Font GetFont(string fontname, string encoding, bool embedded, float size, int style, BaseColor color, bool cached)
    8.     {
    9.         return FontFactory.GetFont("arial unicode ms", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
    10.     }
    11. }

     

     

    如何确定哪些字体在itextsharp中是支持中文的呢,可以通过下面这个小程序验证输出所有的字体名称,及是否支持中文

    通过控制台应用程序执行完成后,打开生成的pdf文件,查看 字体名称是否有中文 " 我支持中文" ,如果存在则表示支持中文,否则不支持中文

    1. Document document = new Document();
    2. PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(@"c:pdfpdf.pdf", FileMode.Create));
    3. document.Open();
    4.  
    5. FontFactory.RegisterDirectories();
    6.  
    7. foreach (var item in FontFactory.RegisteredFonts)
    8. {
    9.     Font font = FontFactory.GetFont(item, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
    10.     document.Add(new Paragraph(item + "<p>我支持中文</p>", font));
    11. }
    12. document.Close();

     

     

    上面说了如何转换html为pdf及怎么解决中文字体的问题,那么怎么使用定义的PdfContentResult呢,

    使用方式一:直接在控制器的Action方法中返回PdfContentResult实例

    1. public class PdfController : Controller
    2.     {
    3.         // GET: Pdf
    4.         public ActionResult Index()
    5.         {
    6.             return new PdfContentResult(null,"index");
    7.         }
    8.     }

     

    使用方式二:添加Controller类的拓展方法,然后在控制器的Action方法中返回对应的拓展方法

    1. public static class ControllerExtensions
    2.   {
    3.       public static PdfContentResult Pdf(this Controller controller, object model)
    4.       {
    5.           return new PdfContentResult(model);
    6.       }
    7.  
    8.       public static PdfContentResult Pdf(this Controller controller, object model, string fileName)
    9.       {
    10.           return new PdfContentResult(model, fileName);
    11.       }
    12.  
    13.       public static PdfContentResult Pdf(this Controller controller, string fileName)
    14.       {
    15.           return new PdfContentResult(fileName);
    16.       }
    17.   }

     

    这种感觉用起来是不是与return view();一样

    1. public class PdfController : Controller
    2. {
    3.     // GET: Pdf
    4.     public ActionResult Index()
    5.     {
    6.         return this.Pdf(null, "index");
    7.     }
    8. }

     

    可能有人会问pdf文档的内容在哪里维护,直接打开Action对应的View视图,像写mvc页面一样布局pdf内容就可以了

     

    至于itextsharp更多功能支持,请参考此文档:http://developers.itextpdf.com/

  • 相关阅读:
    js 闭包
    js 图片放大镜功能
    前端页面优化
    css 背景图片自适应分辨率大小 兼容
    纯css实现箭头
    js 排序算法
    css3 渐变 兼容
    css 兼容性总结
    css3 @keyframe 抖动/变色动画
    关于$.data(element,key,value)与ele.data.(key,value)的区别
  • 原文地址:https://www.cnblogs.com/AlvinLee/p/6138093.html
Copyright © 2011-2022 走看看