zoukankan      html  css  js  c++  java
  • Asp.net MVC Razor视图模版动态渲染PDF,Razor模版生成静态Html

    1.前言

        上一篇文章我开源了轮子,Asp.net Core 3.1 Razor视图模版动态渲染PDF,然后,很多小伙伴有很多私信找我了。那么我下面就简单的给大家说一下,关于小伙伴问的这些问题。

    • 我项目的电子签章部分代码可否开源?

      答:我项目电子签章也是使用第三方的电子签章,电子签章并不是自己实现的,项目里面的电子签章代码无非也是对接第三方的接口。这部分代码开源出去也没有什么意义。我们是使用数字广东的方案,如果您也是使用该数字签章,可以私下沟通我看看能不能帮助您。

    • 电子签章实现难不难,怎么实现自己的电子签章?

      答:电子签章要实现,估计不是太难,按照我的理解,当然我没有具体深入研究(如果这里我有妄自菲薄的意思,请谅解,毕竟我能力有限,只是按照我的理解来分析),我个人觉得电子签章应该就是利用数字证书给PDF签名,然后加密保护文档,然后校验文档的真伪,就要考虑怎么验证这个文档没有被删改,是当初我们签章的这个文档,而且这个签名不能被伪造。个人觉得不是很复杂,但是,电子签章的法律有效性却不是这么简单的。按照国家法律规定,利用的签名平台应该有资质的,国家认可的第三方签章平台,也就是说,私人自己制作的签章,打起官司来,很难得到法律支持。

    • 项目为什么CSS样式不起效?

      答:你是否使用了外链的CSS样式,因为渲染Razor视图是在后台渲染,无法找到外链的文件路径,就使用不了外链的CSS样式,内嵌和内联CSS样式都没啥问题的。

    • 用word或者excel模版他不香吗?为什么要搞个这个东西?

      答:无非是多一个方案,具体你使用什么完全是你自己说了算,你觉得其他方案好就用,你觉得本方案能帮助你就用,不好就不用,我又不收你半毛线,还是想说的是,你其他的方案,能有用CSS那么容易做出来漂亮的表单效果吗?

    • 图片支持吗?

      答:图片要转Base64编码,不支持外连接图片。

    • 前端预览PDF用什么插件?

      答:我目前不用插件,新一代浏览器都支持PDF直接预览,直接就能渲染成PDF呈现,当然你也可以自己集成PDF.JS.我大概看了下,集成也很方便。我之所以不集成,是考虑到我的项目有可能使用IE低版本的情况,PDF.JS可能不支持。所以干脆直接把PDF流推送给浏览器,浏览器要是能预览,就直接呈现,不能预览就下载。

    • 项目支持net Framework吗?为啥报错?

      答:这个问题问的有点多,所以本文后续就以这个再说一下本轮子在net45下的使用。还是那句话,有不对的,欢迎您指正,觉得对你有用的就用,无用的就直接忽视,我又不收你半毛线。

    • 可以用本项目生成静态Html吗?容易被搜索引擎抓取。

      答:可以,后面演示

      2.依赖项目

      <PackageReference Include="TuesPechkin" Version="2.1.1" />
      <PackageReference Include="TuesPechkin.Wkhtmltox.Win32" Version="0.12.2.1" />
      <PackageReference Include="RazorEngine" Version="3.9.3" />
      <PackageReference Include="System.ComponentModel.Annotations" Version="4.5.0" />
      <PackageReference Include="Microsoft.AspNet.Mvc" Version="5.2.3" />
      <PackageReference Include="Nito.AsyncEx" Version="4.0.1" />
      <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
      <Reference Include="Nito.AsyncEx.Concurrent" Version="4.0.1" />
      <Reference Include="Nito.AsyncEx.Enlightenment" Version="4.0.1" />

         3.核心代码

        TuesPechkin插件,首先说一下这个TuesPechkin插件,他其实是利用TuesPechkin.Wkhtmltox进程来转换的。这个插件使用还是要小心的,使用不当可能有线程安全问题,会使得当前工作进程挂起。在IIS下面使用也要注意使用32位的插件。具体使用请看作者的说明:https://github.com/tuespetre/TuesPechkin/blob/develop/README.md

     插件初始化代码:

      private static readonly IConverter PdfConverter = new ThreadSafeConverter(new RemotingToolset<PdfToolset>(
                new Win32EmbeddedDeployment(
                    new TempFolderDeployment())));
    

      

     切记IIS和多线程一定要静态单例。使用

     Win32EmbeddedDeployment

    ThreadSafeConverter
    这两个类。其他的可能让你进程挂起的成为可能。
    还要用到远程工具集的PDF工具集。


    Razor 转Html代码,主要有两种方式:


    第一种使用RazorEngine来转换:这个主要是传递Razor模版进去,转换。

       protected string RunCompileRazorTemplate(object model,string razorTemplateStr)
            {
                if(string.IsNullOrWhiteSpace(razorTemplateStr))
                    throw new ArgumentException("Razor模版不能为空");
    
                var htmlString= Engine.Razor.RunCompile(razorTemplateStr, razorTemplateStr.GetHashCode().ToString(), null, model);
                return htmlString;
            }

    第二种使用ViewEngine。这个主要是自动查找Asp.net MVC里面的View下面的Razor,目前我们项目就是使用这个。

    var viewName = context.RouteData.Values["action"].ToString();
                var result = ViewEngines.Engines.FindView(context, viewName, null);
               
                IExportPdfByHtmlTemplate exportPdfByHtmlTemplate = new PdfByHtmlTemplateExporter ();
    #endif
                if (result.View == null)
                    throw new ArgumentException($"名称为:{viewName}的视图不存在,请检查!");
                 context.HttpContext.Response.ContentType = "application/pdf";
                //context.HttpContext.Response.Headers.Add("Content-Disposition", "attachment; filename=test.pdf");                    
                var html = "";
                using (var stringWriter = new StringWriter())
                {
    
    #if !NET45
                    var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = Value };
                    var viewContext = new ViewContext(context, result.View, viewDictionary, new TempDataDictionary(context.HttpContext, tempDataProvider), stringWriter, new HtmlHelperOptions());
    
                    await result.View.RenderAsync(viewContext);
    #else
                    var viewDictionary = new ViewDataDictionary(new ModelStateDictionary()) { Model = Value };
                    var viewContext = new ViewContext(context, result.View, viewDictionary, context.Controller.TempData, stringWriter);
                    result.View.Render(viewContext, stringWriter);
                    result.ViewEngine.ReleaseView(context, result.View);
    #endif
                    html = stringWriter.ToString();
    
                }

    推送PDF流给客户端,预览PDF主要代码

              context.HttpContext.Response.ContentType = "application/pdf";
        context.HttpContext.Response.AddHeader("Content-Length", buff.Length.ToString());
                context.HttpContext.Response.AddHeader("Content-Disposition", "filename=电子签章PDF-"+DateTime.Now.ToString()+".pdf");
                context.HttpContext.Response.BinaryWrite(buff);
                context.HttpContext.Response.Flush();
                context.HttpContext.Response.Close();
                context.HttpContext.Response.End();
    

      

     这里要注意三个地方,不然一定会踩坑。

    Content-Length要设置,不然谷歌浏览器可能无法下载预览的PDF。
    Content-Disposition不能要attachment,否则可能直接下载不是预览。
    ContentType 要设置"application/pdf"


    Razor转静态Html

    还有一部分人问我怎么利用本插件Razor模版动态生成静态Html,这样容易被百度爬虫录取。
    其实这部分核心代码就是几句代码,非常简单。本项目直接用下面接口即可生成html字符转,自行保存就可以了。

     public interface IHtmlByRazorTemplateExporter
        {
            Task<string> ExportHtmlByRazorTemplateAsync<T>(T data, string htmlTemplate) where T : class;
            string ExportHtmlByRazorTemplate<T>(T data, string htmlTemplate) where T : class;
        }
    

      

    核心:

       protected string RunCompileRazorTemplate(object model,string razorTemplateStr)
            {
                if(string.IsNullOrWhiteSpace(razorTemplateStr))
                    throw new ArgumentException("Razor模版不能为空");
    
                var htmlString= Engine.Razor.RunCompile(razorTemplateStr, razorTemplateStr.GetHashCode().ToString(), null, model);
                return htmlString;
            }

      4.使用方式

    •  目前本项目已经打包成nuget,并上传,使用可以直接项目右键->管理NuGet程序包,查找,然后下载安装。

    •  也可以使用命令安装。install-package JESAI.HtmlTemplate.Pdf.net45
    • 或者直接fork本仓库自己打包,并根据自己情况修改使用。

    自定打包可以修改项目目标框架。项目右键->属性->应用程序,目标框架,修改

    如发现不能修改,可以,项目->右键->编辑项目文件

    然后编译,就可以使用了。

    具体使用

    方式一:

     方式二:

     

    Razor视图模版代码:

    <!DOCTYPE html>
    
    <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
    
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
    
    <body>
        <table border="1" style="800px;height:500px;">
            <tr>
                <td>姓名</td>
                <td>@Model.Name</td>
                <td>性别</td>
                <td>@Model.Sex</td>
            </tr>
            <tr>
                <td>年龄</td>
                <td>@Model.Age</td>
                <td>班级</td>
                <td>@Model.Class</td>
            </tr>
            <tr>
                <td>住址</td>
                <td>@Model.Address</td>
                <td>电话</td>
                <td>@Model.Tel</td>
            </tr>
            <tr>
                <td clospan="2">住址</td>
                <td>@Model.Des</td>
            </tr>
        </table>
    </body>
    </html>

      5.运行效果

     

      6.项目代码

     代码托管:https://gitee.com/Jesai/JESAI.HtmlTemplate.Pdf

  • 相关阅读:
    用例输入单元测试(3)参数化测试方法
    线程文件[MFC]线程优先级设置,下拉列表框ComboBox,复选框CButton,列表框CListBox的使用
    设置系统SetLocalTime设置系统时间
    页面错误毕业设计之错误集锦(六)
    定义数据类型SQL server中SET ANSI_PADDING对char、varchar、nvarchar的影响
    查找关键字算法:静态查找表(Static Search Table)
    密码注册ASP.NET实现忘记密码
    卡函数or1200基于simplespi的SD卡驱动
    目的地返回POJ 2336 动态规划(DP) Ferry Loading II
    坐标序列hdu 1003 解题报告 Max Sum
  • 原文地址:https://www.cnblogs.com/dengjiahai/p/13040005.html
Copyright © 2011-2022 走看看