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/

  • 相关阅读:
    dotnet 控制台读写 Sqlite 提示 no such table 找不到文件
    dotnet 控制台读写 Sqlite 提示 no such table 找不到文件
    dotnet 控制台 Hangfire 后台定时任务
    dotnet 控制台 Hangfire 后台定时任务
    dotnet 获取指定进程的输入命令行
    dotnet 获取指定进程的输入命令行
    PHP sqrt() 函数
    PHP sinh() 函数
    PHP sin() 函数
    PHP round() 函数
  • 原文地址:https://www.cnblogs.com/AlvinLee/p/6138093.html
Copyright © 2011-2022 走看看